c# - 如何在 Windows 通用应用程序 (Windows 10) 中的 markdowntextblock 中格式化聊天对话

标签 c# xaml markdown uwp-xaml

我正在构建一个聊天应用程序,其中包含以下 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 中一样

enter image description here

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

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

更新 View -

<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>

最佳答案

您可以使用 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 chat messaging

希望这能有所进展,并且您可以通过此细节进一步推进。如有任何问题,请随时提出,我很乐意提供帮助。

关于c# - 如何在 Windows 通用应用程序 (Windows 10) 中的 markdowntextblock 中格式化聊天对话,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42883914/

相关文章:

c# - 尝试在 MenuFlyoutSubItem 中添加子菜单项时出现 Xaml 无效标记错误

c# - ASP.NET MVC 为编辑和显示模式应用不同的 DisplayFormat

c# - 测试模拟对象构造函数

c# - 从 XAML 内部创建 C# 类的实例

html - 在 mkdocs 中使用静态 html

c# - 从 SharpDX 中的数据流读取导致内存泄漏

c# - 启动新窗口时如何关闭当前窗口(在代码中)

c# - 更改自定义 ComboBox 样式中的 ItemsPresenter 以显示彼此相邻的项目

pdf - Pandoc:有没有办法在 PDF 中包含来自 markdown 的链接附录?

css - R markdown ioslides - 使用 CSS 更改 kable 字体大小