![](/img/trans.png)
[英]The value of DependencyProperty is not propagated from XAML to code behind
[英]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 控件的默認值,並允許用戶取消設置或將其更改為其他內容。
DependencyProperty.UnsetValue 不能在 XAML 中使用。
http://msdn.microsoft.com/en-us/library/system.windows.dependencyproperty.unsetvalue(v=vs.90).ASPX
就個人而言,我會創建一個單獨的依賴屬性,例如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.