繁体   English   中英

从 xaml 中清除一个 dependencyProperty 值

[英]Clear a dependencyProperty value from the xaml

我有一个控件,它具有属性的默认值。 当控件第一次获得它的 dataContext 集时,它会自动分配这个属性。

现在在 xaml 中,我希望可以取消设置此属性。 我试过将它设置为 x:Null 的空字符串,但后来我收到一个错误,因为该属性没有转换器。 在我希望禁用该功能的极少数情况下,如何简单地从 xaml 取消分配此属性?

最初设置的代码:

void OmniBox_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if( e.NewValue is BindingObjectBaseExtended )
    {
        BindingObjectBaseExtended value = (BindingObjectBaseExtended)e.NewValue;
        this.SetBinding(OmniBox.ContextValidationMessagesProperty, new Binding() { Source = value, Path = new PropertyPath("ValidationMessages") });
    }
}

我想取消设置属性的 xaml。

<Style TargetType="ui:OmniBox">
    <Setter Property="ContextValidationMessages" Value="" />
</Style>

请注意,如果我没有在数据上下文更改时自动设置绑定,那么默认情况下没有验证消息,我必须在 xaml 中执行以下操作来设置它们:

<Style TargetType="ui:OmniBox">
    <Setter Property="ContextValidationMessages" Value="ValidationMessages" />
</Style>

我想要做的是使上述绑定成为我的自定义 OmniBox 控件的默认值,并允许用户取消设置或将其更改为其他内容。

就个人而言,我会创建一个单独的依赖属性,例如bool AutoBindValidation并将其默认为 true。 如果为 false,则在 DataContext 更改时不要做任何事情。 这是一个多一点的自我记录。 根据您究竟要做什么,您可能根本不想公开ContextValidationMessages

如果您真的想按照您发布的方式进行操作,我不确定为什么将其设置为{x:Null}会导致错误(除非属性类型不可为空)。 但是这种方法会有问题,因为DataContextChanged将在 XAML 解析后发生。 因此用户可以将其设置为{x:Null} ,但随后 DataContext 将发生变化,您的代码将设置默认绑定并践踏用户的值。 您可以在控件的构造函数中设置绑定,但是如果 DataContext 没有ValidationMessages属性,您的控件将吐出绑定错误。

这可能是不可能的,我最好的选择是:

<Setter Property="ContextValidationMessages"
        Value="{x:Static DependencyProperty.UnsetValue}" />

但这会引发"Cannot unset setter value" 所以你最好反转你的逻辑或以另一种方式保持属性未设置。

我认为在 xaml 本身中没有任何受支持的方法可以做到这一点。 在您的代码中,您正在ContextValidationMessagesProperty上设置本地值。 您包含的样式设置器将具有较低的 依赖属性优先级,即使对它们进行了评估,它们也会根据指定的值设置一个值 - 不清除它。 也许不是在代码中设置绑定,您可以在 OmniBox 的默认样式中设置一个 Setter 来设置该属性 - 例如

<Setter Property="ContextValidationMessages" Value="{Binding ValidationMessages}" />

如果您必须有条件地设置绑定,那么您可以创建一个自定义 IValueConverter 来检查指定的类型(作为参数传递)。 例如

public class IsAssignableFromConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Type typeParameter = parameter as Type;

        if (typeParameter == null)
            return DependencyProperty.UnsetValue;

        return value != null && typeParameter.IsAssignableFrom(value.GetType());
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return DependencyProperty.UnsetValue;
    }
}

那么你可以像这样使用它:

    <local:IsAssignableFromConverter x:Key="isAssignableConverter" />
    <Style TargetType="ui:OmniBox">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Converter={StaticResource isAssignableConverter}, ConverterParameter={x:Type ui:BindingObjectBaseExtended}}" Value="True">
                <Setter Property="ContextValidationMessages" Value="{Binding ValidationMessages}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>

如果您不希望应用此属性,您可以将 OmniBox 实例的 Style 设置为新样式,并确保将 OverridesDefaultStyle 属性设置为 true

我想另一种选择是创建另一个依赖属性,该属性将在 ContextValidationMessages 属性上调用 ClearValue 但这似乎可能是一个维护问题。

在某些情况下,您可以使用 RelativeSource 将“重置”为父控件的默认值。 例如,我正在使用 DataGrid,这对我重置回“默认值”很有用。

这是数据网格单元格内的文本块。

<TextBlock Text="{Binding ServiceName}">

    <TextBlock.Style>
        <Style>

            <Style.Triggers>

                <!-- Change text color to purple for FedEx -->
                <Trigger Property="TextBlock.Text" Value="FedEx">
                    <Setter Property="TextBlock.Foreground" Value="Purple"/>
                </Trigger>

                <!-- Reset if the cell is selected, since purple on blue is illegible -->
                <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}}}" Value="True">
                    <Setter Property="TextBlock.Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGridCell}}}"/>
                </DataTrigger>

            </Style.Triggers>
        </Style>
    </TextBlock.Style>

</TextBlock>

即使窗口处于非活动状态,这似乎也很聪明,可以继承正确的颜色。

暂无
暂无

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

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