【问题标题】:Cancel binding depending on object type根据对象类型取消绑定
【发布时间】:2016-08-26 13:14:26
【问题描述】:

在我的 WPF 应用程序中,我有一个绑定到文本属性长度的标签:

<Label Content="{Binding Editor.Text.Length}"/>

编辑器对象可以是文本框或复选框。文本框确实具有文本属性,而复选框则没有。
当标签绑定到“复选框编辑器”时,它会在 Visual Studio 中产生警告:

BindingExpression 路径错误:在“对象”上找不到“文本”属性...

这是意料之中的,我想知道是否有任何方法可以告诉绑定引擎不要尝试绑定此值,除非编辑器对象是文本框?

【问题讨论】:

    标签: wpf data-binding


    【解决方案1】:

    您的视图模型的Editor 属性是控件吗?我希望不会,但无论如何。

    您可以编写一个返回值类型的值转换器,然后通过样式中的一系列触发器设置标签的内容。如果编辑器的类型是{x:Type TextBox},请将其设置为您在上面得到的绑定。如果是{x:Type CheckBox},则设为`{Binding Editor.IsChecked}'。

    XAML

    <Label>
        <Label.Style>
            <Style TargetType="Label" BasedOn="{StaticResource {x:Type Label}}">
                <Style.Triggers>
                    <DataTrigger 
                        Binding="{Binding ElementName=Editor, Converter={local:GetTypeConverter}}"
                        Value="{x:Type TextBox}"
                        >
                        <Setter 
                            Property="Content" 
                            Value="{Binding Text.Length, ElementName=Editor}" 
                            />
                    </DataTrigger>
                    <DataTrigger 
                        Binding="{Binding ElementName=Editor, Converter={local:GetTypeConverter}}"
                        Value="{x:Type CheckBox}"
                        >
                        <Setter 
                            Property="Content" 
                            Value="{Binding IsChecked, ElementName=Editor}" 
                            />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Label.Style>
    </Label>
    

    C#

    public class GetTypeConverter : MarkupExtension, IValueConverter
    {
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }
    
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value?.GetType();
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    或者,您的视图模型可以具有一个只读属性,该属性返回该标签中应包含的任何内容,因为该视图模型具有 Editor 并且知道它是什么。暂时叫它EditorLabelValue。大概Editor 绑定到string 属性或bool 属性,这取决于它是哪个编辑器。所以这两个设置器都会为"EditorLabelValue" 提高PropertyChanged,这将返回适当的值。

    我尝试在纯 XAML 中执行此操作,方法是将 Editor 设为 ContentControlContent,然后使用 DataTemplates,但我无法找到一种方法来完成这项工作,而不会出现重设 @ 的例外情况987654336@。

    【讨论】:

    • @EdPlunkett 很好的答案。触发器的好主意。但与 WPF 中的许多内容一样,它有点冗长。我认为我应该按照您的建议在我的视图模型中使用单独的属性,这可能是最干净的方法。
    猜你喜欢
    • 1970-01-01
    • 2016-08-04
    • 1970-01-01
    • 2021-12-30
    • 1970-01-01
    • 2021-03-18
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多