如何从 TextBlock 中删除字典资源引用?

How to remove a dictionary resource reference from a TextBlock?

我有这个元素:

<TextBlock Style="{StaticResource textReplyMessageStyle}">
   <Run x:Name="answerMessage" Text="{Binding Message, Mode = OneWay, FallbackValue = ''}" />
</TextBlock>

而且我需要在 answerMessage 中打印 var Message 的内容(感谢绑定)或字典中的元素(感谢由下面的代码)。

answerMessage.SetResourceReference(Run.TextProperty, "Answer_Message_Not_Selected");

绑定和字典引用一样完全有效,但是在设置资源引用后我找不到使绑定再次起作用的方法。

我尝试以编程方式重新绑定,但没有成功... 我发现的唯一解决方法是以编程方式设置 answerMessage.
的文本 如何从 运行 元素中删除资源引用并使绑定再次生效?

只是为了提供一些上下文,变量 Message 包含一个数字和资源 Answer_Message_Not_Selected 包含文本“未选择”或不同语言的翻译,具体取决于程序中激活的词典。我必须使用动态资源引用,因为程序的语言可以即时更改。

谢谢!

解决此问题的一个简单方法是使 TextBlock 的输出主要取决于 Message 属性.

例如,仅当Message的值不为null时,您才可以将Text的值绑定到Message,否则将其设置为您的资源:

<TextBlock Style="{StaticResource textReplyMessageStyle}">
    <Run x:Name="answerMessage" >
        <Run.Style>
            <Style TargetType="{x:Type Run}">
                
                <Setter Property="Text" Value="{Binding Message, Mode = OneWay, FallbackValue = ''}" />
                
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Message}" Value="{x:Null}">
                        <Setter Property="Text" Value="{StaticResource Answer_Message_Not_Selected}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Run.Style>
    </Run>  
</TextBlock>

请注意,您应该在样式中设置 Text 的起始值,因为在控件初始值设定项中设置的属性将覆盖任何样式设置器!

除了将 Message 的值设置为 null 之外,您还可以做的另一件事是在视图模型中添加 属性 AnswerMessageSelected,更明确地说当 TextBlock 应该更改其目标值时:

<TextBlock Style="{StaticResource textReplyMessageStyle}">
    <Run x:Name="answerMessage" >
        <Run.Style>
            <Style TargetType="{x:Type Run}">
                
                <Setter Property="Text" Value="{Binding Message, Mode = OneWay, FallbackValue = ''}" />
                
                <Style.Triggers>
                    <DataTrigger Binding="{Binding AnswerMessageSelected}" Value="False">
                        <Setter Property="Text" Value="{StaticResource Answer_Message_Not_Selected}" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Run.Style>
    </Run>  
</TextBlock>

而且一般使用这种方法后,可能不需要在后面的代码中使用x:Name引用,因为让ViewModel完成所有工作而不是后面的代码是更好的做法视图:

<TextBlock>
    <TextBlock.Style>
        <Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource textReplyMessageStyle}">

            <Setter Property="Text" Value="{Binding Message, Mode = OneWay, FallbackValue = ''}" />

            <Style.Triggers>
                <DataTrigger Binding="{Binding AnswerMessageSelected}" Value="False">
                    <Setter Property="Text" Value="{StaticResource Answer_Message_Not_Selected}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBlock.Style>
</TextBlock>

我最初的怀疑是正确的,感谢@Jason Tyler @o_w 证实了这一点。
当您设置对 运行 的引用(以及类似的元素)时,您将失去绑定 属性。 我的问题的解决方案就是重新绑定。

Binding b = new Binding(); 
b.Path = new PropertyPath("Message"); 
b.Source = this;  
BindingOperations.SetBinding(answerMessage, Run.TextProperty, b);

此解决方案解决了问题,但可以通过将 Answer_Message_Not_Selected 资源设置为绑定的 Message 元素来解决问题。

Message = Application.Current.Resources["Answer_Message_Not_Selected "].ToString()

如果资源是动态的,就像我的情况一样,您将需要某种观察资源(或字典)的 OnChange 事件,以保持 Message 的内容始终更新。