簡體   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