Windows Phone 7 聊天视图实现

在这篇文章中,将探讨如何在Windows Phone 7应用程序中实现一个聊天视图,该视图能够以对话的形式展示消息列表。此外,还将扩展这个概念,通过添加一个输入文本字段,允许用户与ELIZA(一个AI聊天机器人)进行对话。本文将探讨在回复时如何滚动消息列表,以确保最新的消息始终可见。

可以点击查看代码的实际运行效果。

曾希望在互联网上找到一个不错的C# ELIZA实现(一个经典的聊天应用程序,扮演治疗师的角色),但发现的唯一的实现相当基础。如果知道任何替代方案,请告诉!

简单聊天应用程序的布局使用了一个ConversationView用户控件实例,文本输入位于屏幕底部:

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Grid contribControls:GridUtils.RowDefinitions=",Auto"> <ScrollViewer x:Name="ConversationScrollViewer"> <local:ConversationView x:Name="conversationView" /> </ScrollViewer> <Grid Grid.Row="1" contribControls:GridUtils.RowDefinitions=",," Margin="0,10,0,0"> <Rectangle Fill="White" Grid.RowSpan="2" /> <txt:WatermarkedTextBox Watermark="type a message" TextWrapping="Wrap" AcceptsReturn="True" Padding="0" x:Name="TextInput" GotFocus="TextInput_GotFocus" LostFocus="TextInput_LostFocus" /> <Path Data="m 0,0 l 16,0 l 0,16 l -16,-16" Fill="White" Margin="0,0,5,0" HorizontalAlignment="Right" Grid.Row="2" /> </Grid> </Grid> </Grid>

注意简化的Grid标记,其中字符串",Auto"被用于代替更冗长的RowDefinition XAML元素。WatermarkedTextBox来自WindowsPhoneGeek的文章(它工作得很好——谢谢!)。为了使输入字段看起来像一个对话气泡,添加了一个简单的Path和Rectangle。

当用户点击输入TextBlock时,手机键盘将被显示,允许他们输入消息。这是遇到的第一个主要问题!

当手机键盘显示时,应用程序内容会被“推”上去以腾出空间给键盘。不幸的是,这会导致用户正在回复的消息被推到屏幕顶部之外……

因为ConversationView位于ScrollViewer内,可以滚动以将消息推到屏幕更下方,但这将需要一个负的滚动偏移量,这是不可能的!

为了绕过这个问题,可以添加一个元素,用于在需要时将顶部消息向下“推”。以下标记添加了一个Rectangle,它位于ConversationView上方,有两个Storyboard,用于展开/折叠Rectangle,允许在需要时将消息推下去:

<ScrollViewer x:Name="ConversationScrollViewer"> <StackPanel Orientation="Vertical" x:Name="ConversationContentContainer" VerticalAlignment="Top"> <Rectangle Width="100" Height="0" x:Name="PaddingRectangle"> <Rectangle.Resources> <Storyboard x:Name="PaddingRectangleShowAnim"> <DoubleAnimation Storyboard.TargetName="PaddingRectangle" Storyboard.TargetProperty="(Height)" To="400" Duration="00:00:00.3" /> </Storyboard> <Storyboard x:Name="PaddingRectangleHideAnim"> <DoubleAnimation Storyboard.TargetName="PaddingRectangle" Storyboard.TargetProperty="(Height)" To="0" Duration="00:00:00.3" /> </Storyboard> </Rectangle.Resources> </Rectangle> <local:ConversationView x:Name="conversationView" /> </StackPanel> </ScrollViewer>

可以检测输入TextBlock何时获得焦点,以确定何时显示键盘。使用之前在博客中讨论的Show / Hide扩展方法,可以触发动画,使这个填充矩形在键盘显示或隐藏时增长或收缩:

private void TextInput_GotFocus(object sender, RoutedEventArgs e) { PaddingRectangle.Show(); ApplicationBar.IsVisible = true; } private void TextInput_LostFocus(object sender, RoutedEventArgs e) { PaddingRectangle.Hide(); ApplicationBar.IsVisible = false; }

如果填充矩形使其可见,可以看到它如何推动内容如下:

下一步是确保ConversationView始终滚动,以便最新的消息可见。ScrollViewer有一个ScrollToVerticalOffset方法,可以用来程序性地滚动内容,但由于这不是一个依赖属性,所以不能通过Storyboard进行动画处理。

在这里,使用了为Windows Phone 7跳转列表控件采用的相同技巧,其中使用一个私有依赖属性,在它的更改处理程序中设置滚动偏移值,作为滚动Storyboard的目标:

private DependencyProperty VerticalOffsetProperty = DependencyProperty.Register("VerticalOffset", typeof(double), typeof(MainPage), new PropertyMetadata(0.0, OnVerticalOffsetChanged)); private static void OnVerticalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { MainPage app = d as MainPage; app.OnVerticalOffsetChanged(e); } private void OnVerticalOffsetChanged(DependencyPropertyChangedEventArgs e) { ConversationScrollViewer.ScrollToVerticalOffset((double)e.NewValue); }

使用这个依赖属性,可以创建一个简单的Storyboard和DoubleAnimation来滚动以显示最新的消息:

private void ScrollConvesationToEnd() { // 从当前位置开始 scrollViewerScrollToEndAnim.From = ConversationScrollViewer.VerticalOffset; // 将滚动位置设置为包含内容的高度 scrollViewerScrollToEndAnim.To = ConversationContentContainer.ActualHeight; // 开始! scrollViewerStoryboard.Begin(); }

就这样,一个功能完备的聊天应用程序就完成了。享受吧!

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485