UWP开发入门(八)——聊天窗口和ItemTemplateSelector
我们平常用的最多的APP可能就是企鹅和微信了。有没有想过聊天窗口如何实现的?本篇我们将简单模拟一个聊天窗口。

聊天窗口大致上就是消息的一个集合列表。集合列表最常见的展现形式无非就是ListView。可能有些童鞋会觉得ListView的样式和聊天窗口相去甚远,虽然我们可以通过自定义ItemTemplate来修改元素的显示效果,但如何将ListView的元素以不同样式展现呢?这就要通过ListView的ItemTempateSelector属性来实现了。基本原理是通过条件判断,返回不同的DataTemplate给ListViewItem使用。
首先我们来定义ViewModel层的消息集合,集合共有两种不同类型的消息,分别是普通文本信息和红包消息。这两种又需要区别是接受的消息(来自对方)和发送消息(自己发出)。
public abstract class MessageBase
{
public string Name { get; set; } public DateTime Published { get; set; }
} public class Message : MessageBase
{
public string Comment { get; set; } public bool IsSelf { get; set; }
} public class Gift : Message
{
public int Amount { get; set; }
}
其次我们要定义展现消息的DataTemplate,同样分为普通文字消息和红包消息。MessageDataTemplate和SelfMessageDataTemplate就是左右对称的对话框气泡,GiftDataTemplate就是红包的样式啦。
<DataTemplate x:Key="MessageDataTemplate">
<Grid HorizontalAlignment="Left" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0" CornerRadius="4" Background="LightGray" Padding="15">
<TextBlock Text="{Binding Comment}"></TextBlock>
</Grid>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Foreground="LightGray"></TextBlock>
<TextBlock Text="{Binding Published}" Foreground="LightGray" Margin="10,0,0,0"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate> <DataTemplate x:Key="SelfMessageDataTemplate">
<Grid HorizontalAlignment="Right" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0" CornerRadius="4" Background="Green" Padding="15">
<TextBlock Text="{Binding Comment}" Foreground="White"></TextBlock>
</Grid>
<StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
<TextBlock Text="{Binding Published}" Foreground="LightGray" Margin="0,0,10,0"></TextBlock>
<TextBlock Text="{Binding Name}" Foreground="LightGray"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate> <DataTemplate x:Key="GiftDataTemplate">
<Grid HorizontalAlignment="Left" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Grid Grid.Row="0" CornerRadius="4" Background="Orange" Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="Auto"></RowDefinition>
</Grid.RowDefinitions>
<Ellipse Grid.Row="0" Width="50" Height="50" Fill="Red" Stroke="Gold" StrokeThickness="4"></Ellipse>
<TextBlock Grid.Row="0" Text="红包" TextAlignment="Center" VerticalAlignment="Center"></TextBlock>
<TextBlock Grid.Row="1" Text="{Binding Amount}" TextAlignment="Center"></TextBlock>
<TextBlock Grid.Row="2" Text="{Binding Comment}" TextAlignment="Center" ></TextBlock>
</Grid>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<TextBlock Text="{Binding Name}" Foreground="LightGray"></TextBlock>
<TextBlock Text="{Binding Published}" Foreground="LightGray" Margin="10,0,0,0"></TextBlock>
</StackPanel>
</Grid>
</DataTemplate>
接下来就是如何应用ItemTemplateSelector了,我们需要创建继承自DataTemplateSelector的子类,并且override SelectTemplateCore方法。该方法将我们在App.xaml中定义的DataTemplate资源文件根据集合众不同的元素返回对应的模板。
public class MessageItemDataTemplateSelector : DataTemplateSelector
{
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
if (item is Gift)
{
return App.Current.Resources["GiftDataTemplate"] as DataTemplate;
}
else if (item is Message)
{
if ((item as Message).IsSelf)
{
return App.Current.Resources["SelfMessageDataTemplate"] as DataTemplate;
}
else
{
return App.Current.Resources["MessageDataTemplate"] as DataTemplate;
}
} return base.SelectTemplateCore(item);
}
}
使用之前,我们需要在XAML中声明一个MessageItemDataTemplateSelector类型的实例。
<local:MessageItemDataTemplateSelector x:Key="MessageItemDataTemplateSelector"></local:MessageItemDataTemplateSelector>
然后Binding到ListView的ItemTemplateSelector属性。
<ListView Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
ItemTemplateSelector="{StaticResource MessageItemDataTemplateSelector}"
ItemsSource="{Binding MessageList}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
<Setter Property="Margin" Value="10"></Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView>
运行看一下效果,是不是蛮简单的?

Sample的代码放在全球最大同性交友网站上,地址如下:
https://github.com/manupstairs/UWPSamples
UWP开发入门(八)——聊天窗口和ItemTemplateSelector的更多相关文章
- UWP开发入门(十六)——常见的内存泄漏的原因
本篇借鉴了同事翔哥的劳动成果,在巨人的肩膀上把稿子又念了一遍. 内存泄漏的概念我这里就不说了,之前<UWP开发入门(十三)——用Diagnostic Tool检查内存泄漏>中提到过,即使有 ...
- UWP开发入门系列笔记之(一):UWP初览
标签: 随着微软Build2015带来的好消息,Win10正式版发布的日子已经离我们越来越近了,我们也终于欣喜地看到:一个统一的Windows平台对于开发人员来说充满了吸引力,这局棋下的好大的说--于 ...
- UWP开发入门(十)——通过继承来扩展ListView
本篇之所以起这样一个名字,是因为重点并非如何自定义控件,不涉及创建CustomControl和UserControl使用的Template和XAML概念.而是通过继承的方法来扩展一个现有的类,在继承的 ...
- UWP开发入门(四)——自定义CommandBar
各位好,再次回到UWP开发入门系列,刚回归可能有些不适应,所以今天我们讲个简单的,自定义CommandBar,说通俗点就是自定义类似AppBarButton的东西,然后扔到CommandBar中使用. ...
- UWP开发入门(25)——通过Radio控制Bluetooth, WiFi
回顾写了许久的UWP开发入门,竟然没有讲过通过Windows.Devices.Radios.Radio来控制Bluetooth和WiFi等功能的开关.也许是因为相关的API设计的简单好用,以至于被我给 ...
- UWP开发入门(十一)——Attached Property的简单应用
UWP中的Attached Property即附加属性,在实际开发中是很常见的,比如Grid.Row: <Grid Background="{ThemeResource Applica ...
- UWP开发入门(七)——下拉刷新
本篇意在给这几天Win10 Mobile负面新闻不断的某软洗地,想要证明实现一个简单的下拉刷新并不困难.UWP开发更大的困难在于懒惰,缺乏学习的意愿.而不是“某软连下拉刷新控件都没有”这样的想法. 之 ...
- UWP开发入门(一)——SplitView
接下来会写一个UWP(Universal Windows Platform)开发入门的系列,自己学习到哪里,有什么心得总结,就会写到哪里.本篇对适用于顶层导航的SplitView控件展开讨论. 首先S ...
- UWP开发入门(二十三)——WebView
本篇讨论在UWP开发中使用WebView控件时常见的问题,以及一些小技巧. WebView是实际开发中常用的控件,很多大家抱怨的套网页的应用都是通过WebView来实现的.这里要澄清一个问题,套网页的 ...
- UWP开发入门(二十一)——保持Ui线程处于响应状态
GUI的程序有时候会因为等待一个耗时操作完成,导致界面卡死.本篇我们就UWP开发中可能遇到的情况,来讨论如何优化处理. 假设当前存在点击按钮跳转页面的操作,通过按钮打开的新页面,在初始化过程中存在一些 ...
随机推荐
- ganglia-Monitor
- 可视化库-Matplotlib-Pandas与sklearn结合(第四天)
1. 计算每一种的比例的百分比 import pandas as pd from matplotlib.ticker import FuncFormatter np.random.seed(0) df ...
- LUA全总结
------------------------------------------------------------------------------ --2018.7.21 do --开启或关 ...
- 问题记录,StartCoroutine(“str")问题
StartCoroutine参数为函数字符串名,运行时出错,错误是:无法启动协程函数. 调用格式如下: gameManager.StartCoroutine(LuaOnLevelwasloaded() ...
- LUA 运行期间不独占线程的递归,通过回调实现
function main(d) local function func(d) moveto(d, function() print("d=======", d) d = d - ...
- MyBatis ehcache二级缓存
ehcache二级缓存的开启步骤: 1.导入jar 2.在映射文件中指定用的哪个缓存 3.加一个配置文件,这个配置文件在ehcache jar包中就有 使增删改对二级缓存不刷新: 对一级缓存没有用的, ...
- css常用属性总结:文本属性中的text-align
前面提到text-indent属性,用来实现文本的缩进,今天的text-align使用率可比文本缩进高的多.拿自己现在做的项目上来说,水平居中和垂直居中估计是用到最多了,那我们就先看看它的语法吧! t ...
- 多产生半成品工单的问题 修改带SO的半成品工单无法分配给SO的问题的
原因:验货及VIP带SO的半成品MO无法分配给对应的SO问题, 解决: SELECT SL.ENTERPRISE , SL.ENGINE_ID , SL.SITEID , ML.MO_ID || '_ ...
- 自学jquery,下午实现前后台交互--成为牛逼的女程序员
希望周末能够把搜索质量对比的页面做出来!!! 牛逼的薰衣草程序员,fighting
- 如何使用vsphere client 克隆虚拟机
vSphere 是VMware公司推出一套服务器虚拟化解决方案. 工具/原料 vSphere 测试系统 方法/步骤 1.进入vSphere client,关闭需要克隆的虚拟机win7 2.选中ESXi ...