如何在基于多行的控件中为文本着色
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 属性 并将其绑定到 TextBlock
的 Foreground
属性。
如果您不需要多级日志,请随意删除示例中的 CollapsibleLogEntry
部分。当然,如果您只想处理日志中的文本消息,您可以删除 DateTime 和 Index。如果您想要 MessageType,您也可以添加 Enum。
这个例子已经很完整了,但是如果你不想要所有的"extras"。
环境: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 属性 并将其绑定到 TextBlock
的 Foreground
属性。
如果您不需要多级日志,请随意删除示例中的 CollapsibleLogEntry
部分。当然,如果您只想处理日志中的文本消息,您可以删除 DateTime 和 Index。如果您想要 MessageType,您也可以添加 Enum。
这个例子已经很完整了,但是如果你不想要所有的"extras"。