[英]Problem with Dependency Property and PropertyChangedCallback in WPF
[英]Dependency Property PropertyChangedCallback exception
我在自定義控件中具有以下DependencyProperty
:
public bool HasConnection
{
get { return (bool)GetValue(HasConnectionProperty); }
set { SetValue(HasConnectionProperty, value); }
}
public static readonly DependencyProperty HasConnectionProperty =
DependencyProperty.Register(
"HasConnection",
typeof(bool),
typeof(NetworkNode),
new FrameworkPropertyMetadata(
false,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback(HasConnectionChangedCallBack)));
private static void HasConnectionChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
NetworkNode nn = (NetworkNode)d;
Ellipse el = nn.GetTemplateChild("PART_inner") as Ellipse;
if (el.PART_inner.Visibility == ...) <-- exception el is null
//..code..
}
運行正常,但是如果我更改自定義控件的“屬性”面板中的屬性,則在運行時會引發異常:對象引用未設置為對象的實例。
編輯1:
忘記在Ellipse el = nn.GetTemplateChild("PART_inner") as Ellipse;
帖子中添加一行代碼Ellipse el = nn.GetTemplateChild("PART_inner") as Ellipse;
編輯2:
雖然可以創建BooleanToVisibilityConverter並在Generic.xaml中使用Binding,但是HasConnectionChangedCallBack方法現在為空/無用。
Visibility="{Binding HasConnection, Converter={StaticResource BooleanToVisibiltyConverter}, RelativeSource={RelativeSource TemplatedParent}}"
編輯3:
找到了可能的解決方法。 首先調用屬性回調方法,然后再調用OnApplyTemplate()方法,因此不會在xaml中引發任何異常或錯誤。
在OnApplyTemplate()中,我添加
if (this.HasConnection)
PART_inner.Visibility = System.Windows.Visibility.Visible;
else
PART_inner.Visibility = System.Windows.Visibility.Hidden;
做這個
private static void HasConnectionChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (e.NewValue == null)
return;
NetworkNode nn = (NetworkNode)d;
if (nn == null || nn.Part_inner == null )
return;
if (nn.PART_inner.Visibility == ...) <-- exception
//..code..
}
發生異常的原因是,當通過XAML解析器設置屬性時,尚未實例化UserControl的內容。
XAML解析器通過XAML從上到下進行工作。 UserControl只是用於定義它的XAML的快捷方式,因此,當XAML解析器在外部控件上設置HasConnection=True
時,其內容尚未實例化,因此PART_Inner不存在。
解決方案是在用戶控件中定義HasConnection與依賴它的對象之間的關系,並牢記實例化順序。 例如,如果PART_Inner是一個UserControl,則可以在其Loaded事件中搜索其類型為NetworkNode的父級,以便HasConnection
可以評估HasConnection
。 這可能是需要對現有代碼進行最少更改的解決方案。 保留更改處理程序(包括安全代碼)的狀態,並向包含的控件添加邏輯,該控件從其祖先讀取起始值。
其他選擇是完全不使用DependencyPropertyChanged
回調,而是使用類型為FindAncestor
的RelativeSource
和BooleanToVisibilityConverter
在Visibility屬性上創建綁定。 還有一個想法是使用Trigger
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.