繁体   English   中英

XAML“有条件”绑定

[英]XAML “Conditional” Binding

我有一个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'(类型'对象')

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

开箱即用,直接无法实现。

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

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

不直接#2:您可以尝试“层次化”样式和触发器。 如您所知,Trigger有一个条件。 将你的风格分为两部分:第一部分是不需要“保护”的普通风格,第二部分包含依赖于“Blargh”属性的特征。 将第一个样式设置为默认/正常。 现在创建一个名为“DefinesBlargh”或“HasBlarghDefines”的只读附加属性,用于检查目标对象的datacontext是否实际具有此属性。 现在添加第一个样式的触发器,检测样式控件是否具有“HasBlarghDefined”等于“true”,并在触发器的动作中...

......这就是问题所在。 该怎么办? 你不能再将样式替换为样式的第二部分,因为它可能会删除触发器并反过来停用逻辑(它将是一次性)。 或者,由于尝试在一次更新扫描中尝试两次更改样式,它可能会崩溃。 我其实不知道会发生什么,但我感觉到“有异味”。 更重要的是,改为第二部分将简单地抹去第一部分设置的常见事物。

所以,如果它实际上会运行并替换样式,你必须确保保留原始触发逻辑和第一个样式的其余部分,我建议使用“样式继承”,即基于样式property: 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

所以我的最终解决方案是有一个基本的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);

我能够使用此方法,因为具有“链接”属性的绑定对象仅用于我的派生DataGrid类。

暂无
暂无

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

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