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开发中可能遇到的情况,来讨论如何优化处理. 假设当前存在点击按钮跳转页面的操作,通过按钮打开的新页面,在初始化过程中存在一些 ...
随机推荐
- webdriver定位页面元素时使用set_page_load_time()和JavaScript停止页面加载
webdriver定位页面元素时使用set_page_load_time()和JavaScript停止页面加载 原文:https://my.oschina.net/u/2344787/blog/400 ...
- 学习记录:CONCAT()
连接多个字符串 SELECT * from t_info where phone = CONCAT('12345','678900')
- Spring Boot实践——AOP实现
借鉴:http://www.cnblogs.com/xrq730/p/4919025.html https://blog.csdn.net/zhaokejin521/article/detai ...
- redis一主二从三哨兵
redis做集群的时候有很多种配置方法,一主二从三哨兵这种模式是官网推荐的.,写配置文件链接的时候,写的是哨兵地址,不是IP,用户名,密码之类的. 一主二从很好理解,一个主的redis,实时备份到两个 ...
- window.addEventListener()/window.postMessage(”text“, '*')
1.设置监听 window.addEventListener('message', function (msg) { console.log(msg.data);}) 2.发送 message win ...
- java过滤关键词
敏感词.文字过滤是一个网站必不可少的功能,如何设计一个好的.高效的过滤算法是非常有必要的.前段时间我一个朋友(马上毕业,接触编程不久)要我帮他看一个文字过滤的东西,它说检索效率非常慢.我把它程序拿过来 ...
- Kubernetes集群的安装部署
此文参照https://www.cnblogs.com/zhenyuyaodidiao/p/6500830.html,并根据实操过程略作修改. 1.环境介绍及准备: 1.1 物理机操作系统 物理机操作 ...
- requests.session之set trust_env to disable environment searches for proxies
import requests s = requests.Session() s.trust_env = False This will prevent requests getting any in ...
- qt QTcpServer与QTcpSocket通讯
分类: C/C++ TCP TCP是一个基于流的协议.对于应用程序,数据表现为一个长长的流,而不是一个大大的平面文件.基于TCP的高层协议通常是基于行的或者基于块的. ...
- setitemdata 32位 or 64位
我用SetItemData 和GetItemData把数据库一条数据导入到CListctrl 32位下 程序都可以跑 GetItemData能得到自定义类数据 可以64位得不到?