C# 带有自定义项的UserControl资源不';无法检测到变化
我有一个简单的C# 带有自定义项的UserControl资源不';无法检测到变化,c#,wpf,xaml,user-controls,C#,Wpf,Xaml,User Controls,我有一个简单的UserControlwhere-is-defined属性ItemsSource public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(Dictionary<string, object>), typeof(UserControl1), new FrameworkPropertyM
UserControl
where-is-defined属性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();
}
更新:我向解决方案迈出了一小步。我有下一种风格:
<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
我发现问题在于,您正在为自定义
UserControl
中的ComboBox
控件构建一个新的ItemsSource
,并且您希望MultiSelectCombo.ItemsSource
与UserControl1.ItemsSource
保持同步。当简单地绑定一个字典
时,这种情况是不会发生的,即使绑定一个可观察集合
,这种情况也不会发生,除非您显式地处理它
要完成您所追求的目标,首先您需要自定义控件的ItemsSource
类型能够通知我们集合更改,例如(我将在本例中使用它,正如您在上面的链接中所做的那样)。然后,您需要在您的控制范围内更新组合框
的项源
,以保持它们的同步
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();
}
只需让包装好的
组合框
使用提供给自定义控件的项资源
。在类的静态构造函数中定义DP。public static readonly dependencProperty ItemsSourceProperty;静态YourClassName(){ItemsSourceProperty=DependencyProperty.Register(“ItemsSource”,typeof(Dictionary),typeof(UserControl1),new FrameworkPropertyMetadata(null,new PropertyChangedCallback(UserControl1.OnItemsSourceChanged));}@AnjumSKhan-我试过之后,我收到异常-附加信息:“ItemsSource”属性已由“UserControl1”注册。
将代码上载到您使用的位置。@AnjumSKhan,请检查更新。希望这对您没问题我已经尝试了observateCollection
,但我的控件的ItemsSource
还是一样的。为了澄清,您是否在添加或删除项目时尝试更新控件?另外,是否可以在问题的底部发布用户控件的xaml?也许这会澄清你需要做什么来解决这个问题。我的控件来自此帖子我尝试了ObservableCollection,但仍然是ItemsSource我的控件是相同的((ObservableCollection)e.OldValue)
应该是e.NewValue
?我尝试了“更简单”的示例,但这并不能解决我的问题。不知道为什么…@demo是的,对不起,这是复制粘贴的错误。你是对的,应该是e.NewValue
。这两种解决方案都能解决您的问题吗?似乎您应该能够将UserControl
的ItemsSource
传递到ComboBox
,并且仍然可以使用它。您确定项目已添加到正确的源实例?谢谢,Mike。你的回答帮助我:)。问题是,我如何修改我的可观察集合
。首先,我在循环中添加了Types.Add(element)
等元素。但现在我尝试了nextTypes=newobservetecollection(list)
其中list是我逐个添加的元素的容器。所以现在它起作用了。这样做可以吗?@demo初始化控件很好,只要您了解在Types=new observetecollection(list)
调用之后向list
添加元素不会将它们包括在呈现的控件中。
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();
}
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = (MultiSelectComboBox)d;
control.MultiSelectCombo.ItemsSource = (IEnumerable)e.NewValue;
}