具有自定义ItemsSource的UserControl无法检测更改

时间:2015-12-02 23:47:59

标签: c# wpf xaml user-controls

我有简单的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();
        }

我想动态地更新此属性,但我想知道为什么OnItemsSourceChanged每次使用ItemsSource时都不会触发。所以我很沮丧。 我已尝试Custom ItemsSource property for a UserControl,但这没有帮助,或者我写错了newValueINotifyCollectionChanged_CollectionChanged函数

我的控件来自此帖CodeProject

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

UserControl CodeBehind - 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不为空(从启动开始)。因此,如果我正确理解这种行为,那么问题就在于重绘控件内容。

3 个答案:

答案 0 :(得分:1)

如果你有一个字典作为你的数据类型,并且你在字典中添加或删除了一个值,那么你的属性实际上并没有改变。只有在您实际设置此属性以引用其他字典时才会触发此事件。

如果您需要wpf来自动检测是否在字典中添加或删除了某个项目,则应使用ObservableCollection。

答案 1 :(得分:1)

  1. 用ObservableCollection替换Dictionary,在添加,更新,删除项目时,Dictionary不会触发propertyChanged事件。
  2. 编写自己的Dictionary以手动触发propertychanged事件。

答案 2 :(得分:0)

我发现问题是您要为自定义ItemsSource中的ComboBox控件构建新的UserControl,并且您希望保留MultiSelectCombo.ItemsSource与您的UserControl1.ItemsSource同步。简单地绑定Dictionary时就不会发生这种情况,即使绑定ObservableCollection也不会发生这种情况 - 除非您明确处理它。

要完成您的目标,首先您需要ItemsSource自定义控件的类型确实通知我们收集更改,例如ObservableCollection(我将使用对于这个例子,正如你在上面的链接中所做的那样)。然后,您需要更新控件中ItemsSource的{​​{1}},以使其保持同步。

ComboBox

现在,上面说的是,上面的解决方案是针对更通用的情况,在将其传递到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给您的自定义控件。