【问题标题】:How to format chat conversations in markdowntextblock in Windows Universal application (windows 10)如何在 Windows 通用应用程序(Windows 10)的 Markdowntextblock 中格式化聊天对话
【发布时间】:2017-03-19 07:10:02
【问题描述】:

我正在构建一个聊天应用程序,其中我有以下 xaml 代码 -

<Page
x:Class="MyProject1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d" Background="Black">
<Grid Background="White" Name="mainGrid">

    <Border  BorderBrush="Cyan" BorderThickness="0.2" Margin="3,0,3,3">
        <ListView x:Name="ListView" VerticalAlignment="Bottom" SelectionMode="None" IsItemClickEnabled="True">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <controls:MarkdownTextBlock Name="markdownBlock" Text="{Binding Text}" TextWrapping="Wrap" FontFamily="Segoe-UI">
                    </controls:MarkdownTextBlock>
                </DataTemplate>
            </ListView.ItemTemplate>
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="FontSize" Value="14" />
                    <Setter Property="Foreground" Value="Black" />
                </Style>
            </ListView.ItemContainerStyle>
        </ListView>
    </Border>
</Grid>
</Page>

我在后面的代码中使用以下代码将文本发送到 MarkdownTextBlock 控件

            messages.Add(new Message() { Text = "**Person 1:** " + message });

和响应 -

            messages.Add(new Message() { Text = "**Person 2:** " + activity.Text });

现在的格式是下面这样的纯背景-

第一个人:你好,你好吗?

第二个人:嗨,我做得很好!

我怎样才能格式化这些简单的消息,让对话感觉就像我们在 Skype 中一样

我是 Windows 应用程序开发的新手,我不知道如何将文本格式化为 Markdown 文本块中的对话,您能指导我吗?

我是否需要在 Markdown 控件中创建一个表格并通过在行上设置背景颜色来传递消息?不知道该怎么做。有什么帮助吗?

更新视图 -

<Page
    x:Class="MyProject1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:gif="using:XamlAnimatedGif"   
    xmlns:local="using:LISA_Speech1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
    mc:Ignorable="d" Background="Black">

    <Page.Resources>
        <Style x:Key="MessageItemStyle" TargetType="SelectorItem">
            <Setter Property="Height" Value="Auto" />
            <Setter Property="Width" Value="450" />
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="VerticalContentAlignment" Value="Stretch" />
            <Setter Property="HorizontalAlignment" Value="Stretch" />
            <Setter Property="Padding" Value="10" />
            <Setter Property="Margin" Value="5" />
        </Style>

        <Style
        x:Key="RightAlignedMessageStyle"
        BasedOn="{StaticResource MessageItemStyle}"
        TargetType="SelectorItem">
            <Setter Property="Background" Value="LightGray" />
            <Setter Property="HorizontalAlignment" Value="Right" />
        </Style>

        <Style
        x:Key="LeftAlignedMessageStyle"
        BasedOn="{StaticResource MessageItemStyle}"
        TargetType="SelectorItem">
            <Setter Property="Background" Value="Orange" />
            <Setter Property="HorizontalAlignment" Value="Left" />
        </Style>

        <styleSelectors:MessageContainerStyleSelector
        x:Key="MessageContainerStyleSelector"
        ReceivedStyle="{StaticResource LeftAlignedMessageStyle}"
        Sender="{x:Bind CurrentUser, Mode=OneWay}"
        SentStyle="{StaticResource RightAlignedMessageStyle}" />

        <DataTemplate x:Key="MessageTemplate" x:DataType="messages:Message">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <TextBlock
                Style="{StaticResource BodyTextBlockStyle}"
                Text="{x:Bind Message, Mode=OneWay}"
                TextWrapping="WrapWholeWords" />

                <StackPanel
                Grid.Row="1"
                Margin="0,5,0,0"
                HorizontalAlignment="Right"
                Orientation="Horizontal">
                    <TextBlock
                    HorizontalAlignment="Right"
                    Style="{StaticResource CaptionTextBlockStyle}"
                    Text="{x:Bind SentDate, Mode=OneWay}" />
                </StackPanel>
            </Grid>
        </DataTemplate>

        <ItemsPanelTemplate x:Key="MessageItemPanelTemplate">
            <ItemsStackPanel VerticalAlignment="Bottom" ItemsUpdatingScrollMode="KeepLastItemInView" />
        </ItemsPanelTemplate>
    </Page.Resources>

    <Grid Background="Black" Name="mainGrid">

        <Grid.RowDefinitions>
            <RowDefinition Height="*"></RowDefinition>
            <RowDefinition Height="50"></RowDefinition>
        </Grid.RowDefinitions>

        <Border  BorderBrush="Cyan" BorderThickness="0.2" Margin="3,0,3,3">
            <ListView
    x:Name="Messages"
    Margin="10"
    CanDrag="False"
    CanReorderItems="False"
    IsItemClickEnabled="False"
    IsTapEnabled="False"
    ItemContainerStyleSelector="{StaticResource MessageContainerStyleSelector}"
    ItemTemplate="{StaticResource MessageTemplate}"
    ItemsPanel="{StaticResource MessageItemPanelTemplate}"
    ItemsSource="{x:Bind Text, Mode=OneWay}" />
        </Border>

        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"></ColumnDefinition>
                <ColumnDefinition Width="35"></ColumnDefinition>
            </Grid.ColumnDefinitions>
            <TextBox x:Name="text" KeyUp="TextBox_KeyDown" Grid.Column="0" PlaceholderText="Type something or say 'Start Listening'" FontSize="17" BorderBrush="Purple" Margin="0,10,0,-7" Height="58" VerticalAlignment="Top">
            </TextBox>

            <Button x:Name="button" Click="Button_Click" Grid.Column="1" Height="58" Width="35" Padding="0" Background="Purple" Margin="0,10,0,-7">
                <SymbolIcon x:Name="symbol" Symbol="Microphone" Width="35" HorizontalAlignment="Center" Foreground="White" Margin="-2,-8,-2,-2"/>
            </Button>
        </Grid>


        <MediaElement x:Name="Media"></MediaElement>
    </Grid>
</Page>

【问题讨论】:

    标签: c# xaml markdown uwp-xaml


    【解决方案1】:

    您可以使用 ItemContainerStyleSelector 非常简单地实现这一点。这将允许您创建一些逻辑来获取您的聊天消息对象并确定它是发送还是接收。

    例如,您的模型可能如下所示:

    public class Message
    {
        public Guid Id { get; set; }
    
        public string UserTo { get; set; }
    
        public string UserFrom { get; set; }
    
        public string Message { get; set; }
    
        public DateTime SentDate { get; set; }
    }
    

    然后您将像这样创建 StyleSelector:

    public class MessageContainerStyleSelector : StyleSelector
    {
        public Style SentStyle { get; set; }
    
        public Style ReceivedStyle { get; set; }
    
        public string Sender { get; set; }
    
        protected override Style SelectStyleCore(object item, DependencyObject container)
        {
            var message = item as Message;
            if (message != null)
            {
                return message.UserFrom.Equals(this.Sender, StringComparison.CurrentCultureIgnoreCase)
                           ? this.SentStyle
                           : this.ReceivedStyle;
            }
    
            return base.SelectStyleCore(item, container);
        }
    }
    

    从这里开始,我们需要创建将与此样式选择器一起使用的样式,它们非常简单。它们还可以让您灵活地选择用于发送或接收消息的颜色。

    在您看来,您可能有这样的样式设置:

    <Page.Resources>
        <Style x:Key="MessageItemStyle" TargetType="SelectorItem">
            <Setter Property="Height" Value="Auto" />
            <Setter Property="Width" Value="450" />
            <Setter Property="HorizontalContentAlignment" Value="Stretch" />
            <Setter Property="VerticalContentAlignment" Value="Stretch" />
            <Setter Property="HorizontalAlignment" Value="Stretch" />
            <Setter Property="Padding" Value="10" />
            <Setter Property="Margin" Value="5" />
        </Style>
    
        <Style
            x:Key="RightAlignedMessageStyle"
            BasedOn="{StaticResource MessageItemStyle}"
            TargetType="SelectorItem">
            <Setter Property="Background" Value="LightGray" />
            <Setter Property="HorizontalAlignment" Value="Right" />
        </Style>
    
        <Style
            x:Key="LeftAlignedMessageStyle"
            BasedOn="{StaticResource MessageItemStyle}"
            TargetType="SelectorItem">
            <Setter Property="Background" Value="Orange" />
            <Setter Property="HorizontalAlignment" Value="Left" />
        </Style>
    
        <styleSelectors:MessageContainerStyleSelector
            x:Key="MessageContainerStyleSelector"
            ReceivedStyle="{StaticResource LeftAlignedMessageStyle}"
            Sender="{x:Bind CurrentUser, Mode=OneWay}"
            SentStyle="{StaticResource RightAlignedMessageStyle}" />
    
        <DataTemplate x:Key="MessageTemplate" x:DataType="messages:Message">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>
    
                <TextBlock
                    Style="{StaticResource BodyTextBlockStyle}"
                    Text="{x:Bind Message, Mode=OneWay}"
                    TextWrapping="WrapWholeWords" />
    
                <StackPanel
                    Grid.Row="1"
                    Margin="0,5,0,0"
                    HorizontalAlignment="Right"
                    Orientation="Horizontal">
                    <TextBlock
                        HorizontalAlignment="Right"
                        Style="{StaticResource CaptionTextBlockStyle}"
                        Text="{x:Bind SentDate, Mode=OneWay}" />
                </StackPanel>
            </Grid>
        </DataTemplate>
    
        <ItemsPanelTemplate x:Key="MessageItemPanelTemplate">
            <ItemsStackPanel VerticalAlignment="Bottom" ItemsUpdatingScrollMode="KeepLastItemInView" />
        </ItemsPanelTemplate>
    </Page.Resources>
    

    在这些样式中,您会看到我们使用了两个聊天消息样式继承自的基本样式。在这种情况下,我们使用右/左对齐,因此您的消息将显示在屏幕的任一侧,但在这里您可以根据自己的需要自定义每种样式。

    这里需要指出一些其他的事情,我们还声明了将用于显示布局消息的 DataTemplate。注意这里我们没有做任何自定义。每条消息的布局都相同,容器样式会改变它们在 ListView 中的显示方式。

    此外,底部的 ItemsPanelTemplate 允许 ListView 以聊天样式格式自下而上显示消息。

    关于这一切如何与页面中的 ListView 联系在一起,您现在可以像这样使用 MessageContainerStyleSelector:

    <ListView
        x:Name="Messages"
        Margin="10"
        CanDrag="False"
        CanReorderItems="False"
        IsItemClickEnabled="False"
        IsTapEnabled="False"
        ItemContainerStyleSelector="{StaticResource MessageContainerStyleSelector}"
        ItemTemplate="{StaticResource MessageTemplate}"
        ItemsPanel="{StaticResource MessageItemPanelTemplate}"
        ItemsSource="{x:Bind Messages, Mode=OneWay}" />
    

    当你运行应用程序时,你会得到类似这样的东西:

    希望这是一件好事,您可以通过这个细节进一步了解这一点。如有任何问题,请随时提出,我很乐意为您提供帮助。

    【讨论】:

    • 一直在寻找答案,但发现非常困难。是否可以更新此问题的标签以涵盖 UWP?我只是通过搜索 Windows 10 才设法找到它!
    • 非常感谢詹姆斯。我今天会试试这个,让你知道。
    • 嗨,詹姆斯,我按照你的建议进行了操作。但我在代码方面遇到了一些问题 - 设计视图因无效标记而中断。我在 上遇到错误。我不确定我错过了什么。我只是根据后面的代码将“消息”字段名称更改为“文本”。你能帮我看看我错过了什么吗?
    • @SatheeshPanduga 您可能需要在页面顶部添加 styleSelectors 和消息命名空间。例如xmlns:styleSelectors="using:MyProject.Selectors".
    • 嗨詹姆斯,按照您的建议添加命名空间后.. 我得到以下错误无法将文本值 'KeepLastItemInView' 分配到类型为 'ItemsUpdatingScrollMode' 的属性 'ItemsUpdatingScrollMode' 中。它适用于 。能否请你帮忙?另外,我想使用 Markdown 文本块而不是 Textblock,我会在清除 ItemsPanelTemplate 的错误后立即尝试。
    【解决方案2】:

    我要做的第一件事是自定义控件MessageViewer。在这个中,您可以有一个参数来告诉您消息的方向,或者只是另外两个类MessageViewerInMessageViewerOut,可能是这样的:

    XAML:

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="50"></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
            <ColumnDefinition Width="50"></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <Rectangle Grid.Column="1" Fill="LightBlue" RadiusX="15" RadiusY="15"></Rectangle>
        <TextBlock Grid.Column="1" VerticalAlignment="Center" Margin="10" Text="Some dummy text here"></TextBlock>
    </Grid>
    

    现在,您可以通过代码了解是否需要在此网格的 LEFT 列或 RIGHT 列上显示图像。一切都取决于您显示的文本是来自用户还是您正在发送此文本。 所以,你可以添加一些方法来检查它(或者直接在这个类的构造函数中做:

    MessageViewer(String message, bool orientation)
    MessageViewer msgVwr = new MessageViewer("Your Text", true/false)
    

    ...如果它的true 你的图标将在左边,当它是假的时候在右边。在控件内部,您可以访问各种元素,例如,如果您要为网格命名

    <Grid Name="grdMain">
    

    您可以通过代码(例如 grdMain.Background)访问他的属性,并对其进行设置和更改。

    对于左侧/右侧的空间,您可以使用 interlat 文本框的边距,设置为“10, 10, 30, 10” 用于右侧空间(您的)消息和“30, 10, 10, 10”留空(传入)消息。

    对于一些文本工作,比如粗体或其他,检查你可以放在网格中的元素:你想要的一切:)

    您可以将所有这些元素放入一个简单的ListView 中,以像聊天一样显示它们。

    【讨论】:

    • 谢谢 Martinocom,我也会检查一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-02
    • 1970-01-01
    • 2015-11-09
    • 2015-11-04
    相关资源
    最近更新 更多