如何格式化Windows Universal应用程序中的markdowntextblock中的聊天对话(Windows 10)

时间:2017-03-19 07:10:03

标签: 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 });

现在格式是普通的背景 - 如下 -

人1:你好,你好吗?

人2:嗨,我做得很棒!

我如何格式化这些简单的消息以使对话感觉像我们在skype中那样

enter image description here

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

2 个答案:

答案 0 :(得分:2)

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

希望这是有目共睹的,您可以通过这个细节进一步了解。随意提出任何问题,我很乐意提供帮助。

答案 1 :(得分:1)

我要做的第一件事就是名为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中,以便像聊天一样显示它们。