如何在基于多行的控件中为文本着色

How to color text in a multiline based control

环境:WPF、C#

我想要什么?: 我想显示一个消息日志,其中不同类型的消息(信息、警告、错误)以不同的样式显示。

有什么问题?: 根据我给出的体系结构,我需要使用绑定来完成此操作。目前有一个包含 MessageType(枚举)的 LogMessages 集合。这个集合是我可以用来创建我的绑定的。

在无数示例中,我见过使用 运行 或直接访问富文本控件的解决方案。我做不到。

那么有没有一种方法可以使用绑定和 WPF 给定控件来创建这种效果?也许使用转换器?最好以一种只允许 select 文本的方式,就像您使用常规文本框所做的那样。

感谢任何建议

谢谢, 维德

解决方案

尽管我希望实现一种整体文本框,用户可以在其中 select 不同的消息,就像在浏览器中一样,但我最终还是使用了像 Dairon 一样的样式触发器下面建议。

我现在将这样做,以便用户可以 select 多条消息并将它们作为字符串复制到缓存中。

    <ListBox ItemsSource="{Binding Messages}" BorderBrush="Black"

                HorizontalAlignment="Stretch" Margin="10,70,10,0" Height="107" VerticalAlignment="Top">
        <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid Margin="4">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="Auto" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>

                <TextBlock Text="{Binding Time}" FontWeight="DemiBold" />
                <TextBlock Grid.Column="1" Text="{Binding Message}">
                    <TextBlock.Style>
                        <Style TargetType="{x:Type TextBlock}">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Path=MsgType}" Value="Info">
                                    <Setter Property="Foreground" Value="DarkGray" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding Path=MsgType}" Value="Warning">
                                    <Setter Property="Foreground" Value="DarkOrange" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding Path=MsgType}" Value="Error">
                                    <Setter Property="Foreground" Value="DarkRed" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </TextBlock.Style>
                </TextBlock>

            </Grid>
        </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

我使用了 Federico Berasategui 的示例 here。这个例子很完美,你应该从这里开始。为了处理不同的颜色,我将他的代码更改为:

日志条目 class :

public class LogEntry
{
    public LogEntry(DateTime dateTime, int index, string message, Color textColor)
    {
        DateTime = dateTime;
        Index = index;
        Message = message;
        TextColor = new SolidColorBrush(textColor);
        TextColor.Freeze();
    }

    public DateTime DateTime { get; set; }

    public int Index { get; set; }

    public string Message { get; set; }

    public SolidColorBrush TextColor { get; set; }
}

XAML LogEntry 显示部分:

<DataTemplate DataType="{x:Type local:LogEntry}">
    <Grid IsSharedSizeScope="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition SharedSizeGroup="Index" Width="Auto"/>
            <ColumnDefinition SharedSizeGroup="Date" Width="Auto"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <TextBlock Text="{Binding DateTime}" Grid.Column="0"
                   FontWeight="Bold" Margin="5,0,5,0"/>

        <TextBlock Text="{Binding Index}" Grid.Column="1"
                   FontWeight="Bold" Margin="0,0,2,0" />

        <TextBlock Text="{Binding Message}" Grid.Column="2"
                   TextWrapping="Wrap" Foreground="{Binding TextColor}"/>
    </Grid>
</DataTemplate>

我刚刚在 LogEntry class 中添加了一个 TextColor 属性 并将其绑定到 TextBlockForeground 属性。

如果您不需要多级日志,请随意删除示例中的 CollapsibleLogEntry 部分。当然,如果您只想处理日志中的文本消息,您可以删除 DateTime 和 Index。如果您想要 MessageType,您也可以添加 Enum。

这个例子已经很完整了,但是如果你不想要所有的"extras"。