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开发中可能遇到的情况,来讨论如何优化处理. 假设当前存在点击按钮跳转页面的操作,通过按钮打开的新页面,在初始化过程中存在一些 ...
随机推荐
- 集合-强大的集合工具类:java.util.Collections中未包含的集合工具
任何对JDK集合框架有经验的程序员都熟悉和喜欢java.util.Collections包含的工具方法.Guava沿着这些路线提供了更多的工具方法:适用于所有集合的静态方法.这是Guava最流行和成熟 ...
- PyQt5系列教程(三)用py2exe进行程序打包
软硬件环境 Windows 10 Python 3.4.2 PyQt5 Py2exe 前言 在我们开发了完整的PyQt5项目后,一般都会将其打包成exe文件,方便其他人使用.今天我们就用Py2exe这 ...
- signal模块简介
signal模块简介 最近在看Linux signal 相关内容,signal可以被用来进程间通信和异步处理.Python标准库提供了signal包可以用来处理信号相关.这里讨论的是Unix系统中Py ...
- MySQL GTID (二)
MySQL GTID 系列之二 三.在线将GTID转化为传统模式 环境见上篇系列文章 关闭GTID,不用停止服务,不影响线上业务 3.1 关闭GTID复制,调整为传统复制 #SLVAE实例上停止复制 ...
- 获取当前函数名 __FUNCTION__ 的使用<转>
vs项目中见过这种获取 当前函数名的调用.觉得挺方便的就记录一下. ============================================================== 转载地 ...
- segment_object_model_3d
* *********************************************************************** * This example program sho ...
- @@ERROR和@@ROWCOUNT的用法
1. @ERROR 当前一个语句遇到错误,则返回错误号,否则返回0.需要注意的是@ERROR在每一条语句执行后会被立刻重置,因此应该在要验证的语句执行后检查数值或者是将它保存到局部变量 ...
- 高分辨率下firefox字体和界面自动放大的问题
电脑是高分屏的情况下,如果我们将DPI调成100%,屏幕字体太小,所以我们经常将DPI设置成125%或者其它,这样屏幕看起来会舒服些.但随之而来的是火狐浏览器的字体界面也会放大, 这也会直接导致我们在 ...
- Display file information in the document window
[Display file information in the document window] The status bar is located at the bottom of every d ...
- mysql添加表注释、字段注释、查看与修改注释
1 创建表的时候写注释create table test1( field_name int comment '字段的注释')comment='表的注释'; 2 修改表的注释alter table te ...