简体   繁体   English

从数据模板触发器中的代码获取绑定表达式

[英]Getting binding expressions from code behind from Datatemplate Triggers

I've been set to maintain a wpf application where there is a listbox for logging purposes. 我已经设置好维护一个wpf应用程序,其中有一个用于记录日志的列表框。

The items displayed using listbox are of type TextMessage , ie the listbox is bound to these text messages via 使用列表框显示的项目的类型为TextMessage ,即列表框通过以下方式绑定到这些文本消息

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

Messages are then added with something like 然后在邮件中添加类似

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

This is the definition of the class TextMessage 这是类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; }
}

The xaml definition for the listbox is something like this: 列表框的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>

This works nicely (ie messages are displayed in the listbox in different font weight and color depending on their type), but now for the question : 这很好用(即消息以不同的字体粗细和颜色显示在列表框中,具体取决于消息的类型),但现在出现了以下问题:

Is there any way using BindingExpression or any other means to get the font formatting and coloring from code behind from the xaml definitions ? 是否可以使用BindingExpression或任何其他方式从xaml定义后面的代码中获取字体格式和颜色?

The reason is that I want to just have the formatting in one place (just in the xaml as it is right now) but still be able to reuse it when I want to copy the contents (using code behind) including font formatting to the clipboard. 原因是我只想将格式放在一个位置(现在就在xaml中),但是当我想要将包括字体格式在内的内容(使用后面的代码)复制到剪贴板时,仍然能够重用它。

Example: 例:

    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();
    }

Since I'm new to wpf, I'd really appreciate if someone has a tip for solving this. 由于我是wpf的新手,如果有人能解决此问题,我将不胜感激。 (I've tried hard to find an solution here at stackoverflow, but so far I've been unsuccessful) (我已经尽力在stackoverflow上找到解决方案,但是到目前为止,我一直没有成功)

Thanks in advance, 提前致谢,

King regards Magnus 国王问候马格努斯

Make a ContentPresenter with Content set to your TextMessage. 使用Content设置为TextMessage的ContentPresenter。 Set the ContentTemplate to listBox.ItemTemplate and apply the template. 将ContentTemplate设置为listBox.ItemTemplate并应用模板。 It will create the visuals (TextBlock in this case). 它将创建视觉效果(在这种情况下为TextBlock)。 Then, just parse off the values from the TextBlock. 然后,只需解析TextBlock中的值即可。

Also, your RichTextBox selection code wasn't working quite right so I fixed that by just inserting TextRanges to the end of it instead of trying to get the selection right. 另外,您的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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM