【问题标题】:Getting binding expressions from code behind from Datatemplate Triggers从 Datatemplate Triggers 后面的代码中获取绑定表达式
【发布时间】:2016-08-25 09:29:52
【问题描述】:

我已被设置为维护一个 wpf 应用程序,其中有一个用于记录目的的列表框。

使用列表框显示的项目类型为TextMessage,即列表框通过以下方式绑定到这些文本消息

ObservableCollection<TextMessage> Messages; listBox.DataContext = Messages;

然后在消息中添加类似

的内容

Messages.Add(new TextMessage("Test", TypeOfMessage.Headline));

这是TextMessage类的定义

public enum TypeOfMessage
{
    Normal,
    Headline,
    Focus,
    Important,
    Fail,
    Success
}

public class TextMessage
{
    public TextMessage(string content, TypeOfMessage typeOfMessage)
    {
        Content = content;
        TypeOfMessage = typeOfMessage;
        CreationTime = DateTime.Now;
    }

    public string Content { get; }
    public TypeOfMessage TypeOfMessage { get; }
    public DateTime CreationTime { get; }
}

列表框的 xaml 定义如下所示:

    <ListBox x:Name="listBox" HorizontalAlignment="Left" Height="196" Margin="101,77,0,0" VerticalAlignment="Top" Width="256" ItemsSource="{Binding}" SelectionMode="Multiple">


        <ListBox.InputBindings>
            <KeyBinding
                    Key="C"
                    Modifiers="Control"
                    Command="Copy"
                />
        </ListBox.InputBindings>
        <ListBox.CommandBindings>
            <CommandBinding 
                    Command="Copy"
                    Executed="DoPerformCopy"
                />
        </ListBox.CommandBindings>



        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock x:Name="TextToShow"  Text="{Binding Content}"></TextBlock>
                <DataTemplate.Triggers>
                    <DataTrigger Binding="{Binding TypeOfMessage}" Value="Normal">
                        <Setter TargetName="TextToShow" Property="Foreground" Value="Black"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding TypeOfMessage}" Value="Focus">
                        <Setter TargetName="TextToShow" Property="Foreground" Value="Black"/>
                        <Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding TypeOfMessage}" Value="Headline">
                        <Setter TargetName="TextToShow" Property="Foreground" Value="RoyalBlue"/>
                        <Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding TypeOfMessage}" Value="Important">
                        <Setter TargetName="TextToShow" Property="Foreground" Value="Red"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding TypeOfMessage}" Value="Fail">
                        <Setter TargetName="TextToShow" Property="Foreground" Value="Red"/>
                        <Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding TypeOfMessage}" Value="Success">
                        <Setter TargetName="TextToShow" Property="Foreground" Value="Green"/>
                        <Setter TargetName="TextToShow" Property="FontWeight" Value="Bold"/>
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </ListBox.ItemTemplate>


    </ListBox>

这很好用(即消息以不同的字体粗细和颜色显示在列表框中,具体取决于它们的类型),但现在问题是:

有没有办法使用 BindingExpression 或任何其他方式从 xaml 定义中的代码中获取字体格式和颜色?

原因是我只想将格式设置在一个地方(就像现在一样在 xaml 中),但是当我想复制内容(使用后面的代码)包括字体格式时仍然能够重用它到剪贴板。

例子:

    private void DoPerformCopy()
    {
        RichTextBox rtb = new RichTextBox();
        foreach (TextMessage message in (listBox as ListBox)?.SelectedItems.Cast<TextMessage>().ToList())
        {
            TextPointer startPos = rtb.CaretPosition;
            rtb.AppendText(message.Content);
            rtb.Selection.Select(startPos, rtb.CaretPosition.DocumentEnd);
            //
            // Here it would be very nice to instead having multiple switch statements to get the formatting for the 
            // TypeOfMessage from the xaml file.
            SolidColorBrush scb = new SolidColorBrush(message.TypeOfMessage == TypeOfMessage.Fail ? Colors.Red);
            //

            rtb.Selection.ApplyPropertyValue(RichTextBox.ForegroundProperty, scb);
        }
        // Now copy the whole thing to the Clipboard
        rtb.Selection.Select(rtb.Document.ContentStart, rtb.Document.ContentEnd);
        rtb.Copy();
    }

由于我是 wpf 的新手,如果有人有解决此问题的提示,我将不胜感激。 (我已经在stackoverflow上努力寻找解决方案,但到目前为止我一直没有成功)

提前致谢,

国王的问候 马格努斯

【问题讨论】:

  • 啊...刚刚注意到一个解决方案是冒险沿着listBox.ItemTemplate.Triggers的路径前进

标签: c# wpf xaml listbox binding-expressions


【解决方案1】:

制作一个 ContentPresenter 并将 Content 设置为您的 TextMessage。将 ContentTemplate 设置为 listBox.ItemTemplate 并应用模板。它将创建视觉效果(在本例中为 TextBlock)。然后,只需解析 TextBlock 中的值。

此外,您的 RichTextBox 选择代码运行不正确,因此我通过将 TextRanges 插入到它的末尾而不是尝试正确选择来解决此问题。

private void DoPerformCopy(object sender, EventArgs e)
{
    RichTextBox rtb = new RichTextBox();
    foreach (TextMessage message in (listBox as ListBox)?.SelectedItems.Cast<TextMessage>().ToList())
    {
        ContentPresenter cp = new ContentPresenter();
        cp.Content = message;
        cp.ContentTemplate = listBox.ItemTemplate;
        cp.ApplyTemplate();
        var tb = VisualTreeHelper.GetChild(cp, 0) as TextBlock;
        var fg = tb.Foreground;
        var fw = tb.FontWeight;

        var tr = new TextRange(rtb.Document.ContentEnd, rtb.Document.ContentEnd);
        tr.Text = message.Content;
        tr.ApplyPropertyValue(RichTextBox.ForegroundProperty, fg);
        tr.ApplyPropertyValue(RichTextBox.FontWeightProperty, fw);
    }
    // Now copy the whole thing to the Clipboard
    rtb.Selection.Select(rtb.Document.ContentStart, rtb.Document.ContentEnd);
    rtb.Copy();
}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-14
  • 2017-08-05
  • 1970-01-01
  • 2012-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多