簡體   English   中英

帶有自定義ItemsSource的UserControl無法檢測到更改

[英]UserControl with custom ItemsSource doesn't detect changes

我有簡單的UserControl在哪里定義屬性ItemsSource

public static readonly DependencyProperty ItemsSourceProperty =
         DependencyProperty.Register("ItemsSource", typeof(Dictionary<string, object>), typeof(UserControl1), new FrameworkPropertyMetadata(null,
    new PropertyChangedCallback(UserControl1.OnItemsSourceChanged)));

public Dictionary<string, object> ItemsSource
    {
        get { return (Dictionary<string, object>)GetValue(ItemsSourceProperty); }
        set
        {
            SetValue(ItemsSourceProperty, value);
        }
    }

private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UserControl1 control = (UserControl1)d;
            control.DisplayInControl();
        }

我想使此屬性動態更新,但我想知道為什么在ItemsSource發生某些情況時不會每次觸發OnItemsSourceChanged 所以我很傷心。 我已經嘗試了UserControl的Custom ItemsSource屬性,但這無濟於事,或者我編寫了錯誤的newValueINotifyCollectionChanged_CollectionChanged函數


我的控制權來自此Post CodeProject


我的代碼:UserControl XAML- http ://pastie.org/10606317

用戶控件代碼隱藏- http://pastie.org/10606322

控制用法-

<controls:MultiSelectComboBox SelectedItems="{Binding SelectedCategories, Mode=TwoWay}" Grid.Column="0" Grid.Row="0" x:Name="CategoriesFilter" DefaultText="Category" ItemsSource="{Binding Categories }" Style="{StaticResource FiltersDropDowns}"/>

更新:我已邁出了很小的一步來解決問題。 我有下一種風格:

<Style.Triggers>
            <DataTrigger Binding="{Binding ItemsSource, RelativeSource={RelativeSource Self}}" Value="{x:Null}">
                <Setter Property="IsEnabled" Value="False" />
            </DataTrigger>
            <DataTrigger Binding="{Binding ItemsSource.Count, RelativeSource={RelativeSource Self}}" Value="0">
                <Setter Property="IsEnabled" Value="False" />
            </DataTrigger>
        </Style.Triggers>

我將其應用於控件(如果沒有itemSource,則禁用控件)。 在單擊時更新控件源時,我看到控件已啟用,因此ItemsSource不會為空(從開始就為空)。 因此,如果我正確理解此行為,那么現在的問題只是在重繪控件內容中。

如果您有一個字典作為您的數據類型,並且您在字典中添加或刪除了一個值,那么您的屬性實際上並沒有發生變化。 僅當您實際上已將此屬性設置為引用其他字典時,才會觸發此事件。

如果需要wpf自動檢測是否在字典中添加或刪除了一項,則應使用ObservableCollection。

  1. 用ObservableCollection替換Dictionary,添加,更新或刪除項目時Dictionary不會觸發propertyChanged事件。
  2. 編寫自己的字典來手動觸發propertychanged事件。

我看到問題在於您正在為自定義UserControlComboBox控件構建新的ItemsSource ,並且希望MultiSelectCombo.ItemsSourceUserControl1.ItemsSource保持同步。 如果僅綁定Dictionary ,則不會發生這種情況;即使綁定ObservableCollection ,也不會發生這種情況-除非您明確處理它。

為了完成您要做的事情,首先,您需要將自定義控件的ItemsSource為確實會通知我們集合更改的類型,例如ObservableCollection (在本示例中,我將使用它,就像您在上面的鏈接)。 然后,您需要在控件中更新ComboBoxItemsSource ,以使其保持同步。

private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var control = (MultiSelectComboBox)d;

    // Since we have to listen for changes to keep items synced, first check if there is an active listener to clean up.
    if (e.OldValue != null)
    {
        ((ObservableCollection<Node>)e.OldValue).CollectionChanged -= OnItemsSource_CollectionChanged;
    }

    // Now initialize with our new source.
    if (e.NewValue != null)
    {
        ((ObservableCollection<Node>)e.NewValue).CollectionChanged += OnItemsSource_CollectionChanged;
        control.DisplayInControl();
    }
}

private void OnItemsSource_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    DisplayInControl();
}

就是說,上面的解決方案是針對更通用的情況的,在這種情況下,您可能需要對傳遞給自定義控件的ItemsSource進行處理,然后再將其傳遞到MultiSelectCombo.ItemsSource 在當前的情況下,然而,你只是建立集合Node ,以給定集合完全匹配Node 如果可以保證的話,您的解決方案可能會簡單得多:

private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var control = (MultiSelectComboBox)d;
    control.MultiSelectCombo.ItemsSource = (IEnumerable)e.NewValue;
}

只需讓包裝ComboBox使用提供給自定義控件的ItemsSource

暫無
暫無

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

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