我有一个DataTrigger附加到TextBlock的样式,定义如下:
<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)'上找不到'链接'属性。 BindingExpression:路径=链接; DataItem ='DataRowView'(HashCode = 53681904); target元素是'TextBlock'(Name =''); target属性是'NoTarget'(类型'Object')
这是预期的行为,但我想知道是否有办法告诉XAML中的处理器仅在“Link”属性存在时应用(即在尝试绑定之前检查属性,或者其他一些方法)不打印错误)。这可能吗?
答案 0 :(得分:1)
开箱即用,直接无法实现。
不开箱即用:您可以编写自己的BindingExtension,其行为类似:如果道具存在则绑定,否则忽略。你也可以,关闭报告绑定错误,但当然通常不需要。
不直接:您可以创建某种类型的附加属性,然后设置此类属性而不是设置绑定。你的属性设置器将附加到datacontext-changes并检查对象和可视组件,因为它们飞来飞去并设置绑定。
不直接#2:您可以尝试“层次化”样式和触发器。如您所知,Trigger有一个条件。将你的风格分为两部分:第一部分是不需要“保护”的普通风格,第二部分包含依赖于“Blargh”属性的特征。将第一个样式设置为默认/正常。现在创建一个名为“DefinesBlargh”或“HasBlarghDefines”的只读附加属性,用于检查目标对象的datacontext是否实际具有此属性。现在添加第一个样式的触发器,检测样式控件是否具有“HasBlarghDefined”等于“true”,并在触发器的动作中...
......这就是问题所在。该怎么办?你不能再将样式替换为样式的第二部分,因为它可能会删除触发器并反过来停用逻辑(它将是一次性)。或者,由于尝试在一次更新扫描中尝试两次更改样式,它可能会崩溃。我其实不知道会发生什么,但我感觉到“有异味”。更重要的是,改为第二部分将简单地删除第一部分设置的常见事物。
所以,如果它实际上会运行并替换样式,你必须确保保留原始触发逻辑和第一种样式的其余部分,我建议使用“样式继承”,即基于-on style属性: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
恕我直言,只需要工作。
编辑:忘记过关键链接:The MultiStyle
答案 1 :(得分:0)
所以我的最终解决方案是拥有一个实现相关样式的基础DataGrid类,减去“Link”特定数据触发器。然后我有了一个从我的基类派生的新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类。