4

我有一个附加到 TextBlock 样式的 DataTrigger,定义如下:

<DataTrigger Binding="{Binding Path=Link, Converter={StaticResource HasContentConverter}}" Value="True">
    <Setter Property="TextDecorations" Value="Underline" />
    <Setter Property="Cursor" Value="Hand" />
</DataTrigger>

我遇到的问题是我有多个对象最终使用这种样式,其中一些包含“链接”属性,而另一些则不包含。每当系统遇到不存在的对象时,它就会在输出窗口中打印此错误:

BindingExpression 路径错误:在“对象”“DataRowView”(HashCode=53681904)上找不到“Link”属性。绑定表达式:路径=链接;DataItem='DataRowView' (HashCode=53681904); 目标元素是'TextBlock'(名称='');目标属性是“NoTarget”(类型“对象”)

这是预期的行为,但是我想知道是否有办法告诉 XAML 中的处理器仅在“链接”属性存在时才应用(即在尝试绑定之前检查该属性,或者其他一些不存在的方法打印错误)。这可能吗?

4

2 回答 2

1

开箱即用和直接都是不可能的。

不是开箱即用:您可以编写自己的 BindingExtension,其行为如下:如果道具存在则绑定,否则忽略。你也可以,khem,关闭报告绑定错误,但当然这通常是不想要的。

不直接:您可以创建某种类型的附加属性,然后设置此类属性而不是设置绑定。您的属性设置器将附加到 datacontext-changes 并在对象和可视组件飞来飞去时检查它们并设置绑定与否。

不直接#2:您可以尝试“分层”样式和触发器。如您所知,触发器有一个条件。将您的样式分为两部分:第一部分是不需要“保护”的通用样式,第二部分包含依赖于具有“Blargh”属性的功能。将第一个样式设置为默认/正常。现在创建一个名为“DefinesBlargh”或“HasBlarghDefines”的只读附加属性,用于检查目标对象的数据上下文是否确实具有此类属性。现在向第一个样式添加一个触发器,该触发器检测样式控件是否具有“HasBlarghDefined”等于“true”,并且在触发器的操作中......

...这就是问题所在。在那里做什么?您不能再次将样式替换为样式的第二部分,因为它可能会删除触发器并进而停用逻辑(这将是一次性的)。或者,它可能会由于尝试在一次更新扫描中更改两次样式而简单地崩溃。我实际上不知道会发生什么,但我感觉到“气味”。此外,更改为第二部分只会删除第一部分设置的常见内容。

因此,如果它实际上会运行并替换样式,则必须确保保留原始触发逻辑和第一个样式的其余部分,我建议使用“样式继承”,即基于样式属性:http ://wpftutorial.net/StyleInheritance.html即不要创建两个单独的部分,而是用所有常见的东西制作一个“基础部分”,以及一个基于第一个和添加了不安全的额外内容。现在动态地重新替换为专门的对应物更合理一些。

或者,如果你对布局有一些控制,你可以变得聪明:为什么将两种样式应用于同一个组件?在控件的某个外部边界上设置一般样式并将额外的触发器放置在那里,并让触发器将小的不安全的第二个样式应用于控件。

如果您确实必须针对样式的两个部分都针对一个控件并且不能使用“基于”或者如果它根本不起作用等,您可以做另一个聪明的技巧:使用MultiStyle允许您定义合并的样式二/三/+其他样式合二为一,然后构建触发器层次结构如下:

multitrigger
   condition: HasBlarghDefined = TRUE
   condition: your own data condition
   setter: set style = multistyle of "generalpart" and "usnafepart"
multitrigger
   condition: HasBlarghDefined = FALSE
   condition: your own data condition
   setter: set style = just a generalpart

恕我直言,那必须工作。

编辑:忘记过去的关键链接:MultiStyle

于 2012-08-13T19:48:10.943 回答
0

所以我对此的最终解决方案是拥有一个实现相关样式的基本 DataGrid 类,减去“链接”特定数据触发器。然后我有一个从我的基类派生的新 DataGrid 类,其中包含专门创建数据触发器的代码:

Binding binding = new Binding("Link");
binding.Converter = new MDTCommon.Converters.HasContentConverter();
DataTrigger trigger = new DataTrigger();
trigger.Binding = binding;
trigger.Value = true;
Setter setter1 = new Setter(TextBlock.TextDecorationsProperty, TextDecorations.Underline);
Setter setter2 = new Setter(TextBlock.CursorProperty, Cursors.Hand);
trigger.Setters.Add(setter1);
trigger.Setters.Add(setter2);
Style style = FindResource("DefaultStyleInQuestion") as Style;
style.Triggers.Add(trigger);

我之所以能够使用此方法,是因为具有“Link”属性的绑定对象仅在我的派生 DataGrid 类中使用。

于 2012-08-15T15:37:55.047 回答