我有简单的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不为空(从启动开始)。因此,如果我正确理解这种行为,那么问题就在于重绘控件内容。
答案 0 :(得分:1)
如果你有一个字典作为你的数据类型,并且你在字典中添加或删除了一个值,那么你的属性实际上并没有改变。只有在您实际设置此属性以引用其他字典时才会触发此事件。
如果您需要wpf来自动检测是否在字典中添加或删除了某个项目,则应使用ObservableCollection。
答案 1 :(得分:1)
答案 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
给您的自定义控件。