簡體   English   中英

綁定到 TreeView SelectedItem 用作 ItemsSource 但不適用於自定義 DependencyProperty

[英]Binding to TreeView SelectedItem works as ItemsSource but not for custom DependencyProperty

我有一個 TreeView,它的 ItemsSource 有一個 ICollection<...>。 現在我正在嘗試在其他一些控件中使用 SelectedItem。 出於某種原因,我可以使用 ElementName 為 ListView 正確設置綁定,但是當我嘗試為自定義 DependencyProperty 實現相同的綁定時,它永遠不會更新。

這是 XAML(ListView 有效,MyControl 無效):

<ListView ItemsSource="{Binding ElementName=myTreeView, Path=SelectedItem.Children}" />
<modules:MyControl Grid.Row="1" Blubbi="{Binding ElementName=myTreeView, Path=SelectedItem}" />

以及 MyControl 的 DependencyProperty:

public static readonly DependencyProperty BlubbiProperty = DependencyProperty.Register(
    nameof(Blubbi), typeof(object), typeof(MyControl), new PropertyMetadata(default(object)));

public object Blubbi
{
    get => (object) GetValue(BlubbiProperty);
    set => SetValue(BlubbiProperty, value);
}

我懷疑 DependencyProperty 的實現有些問題,但我不知道是什么。

我認為您的依賴屬性在技術上沒有任何問題,但它的實現方式看起來也不是特別有用。 通常在實現依賴屬性時,您希望在它接收到新值時發生一些事情。 最基本的方法是使用值更改回調。 例如:

public static readonly DependencyProperty BlubbiProperty = DependencyProperty.Register(
    nameof(Blubbi), typeof(object), typeof(MyControl),
    new PropertyMetadata(default(object), (d, e) => ((MyControl)d).OnBlubbiChanged(e.oldValue, e,newValue)));

private void OnBlubbiChanged(object oldValue, object newValue)
{
    // Do something here
}

你也可以做更高級的事情來響應新的傳入值,但通常不需要。 如果你想了解更多,這里有一篇文章

現在所有這一切都適用於任何DependencyObject ,但如果您是從FrameworkElement擴展的元素,大多數元素都這樣做,那么您可以使用FrameworkPropertyMetadata代替PropertyMetadata ,后者以FrameworkPropertyMetadataOptions的形式提供一些額外的便利功能。

因此,假設您在元素的OnRender覆蓋中使用此屬性,那么您可以確保在屬性值更改時渲染自動失效,以便再次調用OnRender

public static readonly DependencyProperty BlubbiProperty = DependencyProperty.Register(
    nameof(Blubbi), typeof(object), typeof(MyControl),
    new FrameworkPropertyMetadata(default(object), FrameworkPropertyMetadataOptions.AffectsRender));

此外,如果您的元素是使用 XAML 定義的模板來表示自身的Control ,那么您可以保持依賴屬性不變,並通過TemplateBinding在您的控件模板中使用它。

<ControlTemplate TargetType="{x:Type myNamespace:MyControl}">
    <TextBlock Text="{TemplateBinding Blubbi}" />
</ControlTemplate>

所以當你說你的財產永遠不會更新時,我不得不問你是怎么知道的? 您提供的代碼不完整,但看起來您實際上並沒有對屬性進行任何可以明顯改變它的事情。

作為附加說明,因為這經常讓人們感到驚訝,所以您為包裝依賴項屬性而定義的屬性將永遠不會通過綁定調用。 綁定使用依賴 object 系統直接更新依賴屬性。 盡管需要包裝器屬性才能從 XAML 設置屬性,但在處理依賴屬性時實際上並未調用它。 換句話說,包裝器屬性的設置器中的斷點永遠不會命中。 所以,永遠不要在包裝屬性中放置任何重要的邏輯。


編輯:如果您仍在努力找出問題所在,您可以通過將TraceLevel附加屬性設置為High來獲取綁定以將調試信息打印到調試器的 output window,如下所示:

<modules:MyControl
    xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase"
    Blubbi="{Binding ElementName=myTreeView, Path=SelectedItem, diag:PresentationTraceSources.TraceLevel=High}" />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM