我有一个带有ItemsSource属性的UserControl。由于基本UserControl类没有实现ItemsSource,我必须创建自己的依赖属性,如下所示:
#region ItemsSource Dependency Property
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(MonthViewControl),
new PropertyMetadata(OnItemsSourceChanged));
static void OnItemsSourceChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
(obj as MonthViewControl).OnItemsSourceChanged(e);
}
private void OnItemsSourceChanged(DependencyPropertyChangedEventArgs e)
{
RefreshLayout();
}
public IEnumerable ItemsSource
{
get
{
return (base.GetValue(ItemsSourceProperty) as IEnumerable);
}
set
{
base.SetValue(ItemsSourceProperty, value);
}
}
#endregion
现在在我的ViewModel中,我有一个Events属性,它是EventItem项的ICollectionView,如下所示:
private ObservableCollection<Controls.EventCalendar.EventItem> eventItems;
private CollectionViewSource events;
public System.ComponentModel.ICollectionView Events
{
get
{
if (events == null)
{
events = new CollectionViewSource();
events.Source = eventItems;
}
return events.View;
}
}
我面临的问题是,在我的View中,当我绑定到Events属性,并且我将一个Item添加到eventItems时,UserControl将不会触发ItemsSourceChanged事件,因此不会更新UI。 为了测试,我在视图中添加了一个简单的列表框,它也绑定到Events属性。这就像一个魅力。对eventItems observableCollection的更新反映在ListBox中。
我认为它与我的ItemsSource依赖属性有关。也许我需要使用继承表单ItemsControl而不是UserControl的自定义控件?
为了帮助您了解我的问题:我正在尝试创建一个类似控件的日历,用于显示事件/议程条目(类似于Google日历)。它就像一个魅力。调整控件大小时更新UI。唯一剩下的就是ItemsSource更改后的自动更新。
希望有人可以提供帮助。
编辑:我发布的那一刻我意识到事件无法触发,因为ItemsSource属性不会更改。它是基础集合的变化。但是,我不是那样处理的。我需要实现什么才能使其工作。只是暗示就足够了。我不需要每个实现细节。
答案 0 :(得分:6)
在Reflector中打开PresentationFramework.dll并查看System.Windows.Controls.ItemsControl,显示以下内容:
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable),
typeof(ItemsControl), new FrameworkPropertyMetadata(null,
new PropertyChangedCallback(ItemsControl.OnItemsSourceChanged)));
private static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
ItemsControl control = (ItemsControl) d;
IEnumerable oldValue = (IEnumerable) e.OldValue;
IEnumerable newValue = (IEnumerable) e.NewValue;
ItemValueStorageField.ClearValue(d);
if ((e.NewValue == null) && !BindingOperations.IsDataBound(d, ItemsSourceProperty))
{
control.Items.ClearItemsSource();
}
else
{
control.Items.SetItemsSource(newValue);
}
control.OnItemsSourceChanged(oldValue, newValue);
}
不知道我的预感是什么RefreshLayout
它与ObservableCollection<T>
被包裹的方式有关,因为上面的代码不知道具体的集合类型是什么,因此由被包裹的类型处理;在这种情况下,ObservableCollection<T>
尝试修改您的属性,如下所示返回默认视图,并将ItemsSource
属性调整为更类似于框架中的上述代码,并从那里向后工作。
private ObservableCollection<Controls.EventCalendar.EventItem> eventItems;
private ICollectionview eventsView;
public System.ComponentModel.ICollectionView Events
{
get
{
if (eventsView == null)
eventsView = CollectionViewSource.GetDefaultView(eventItems);
return eventsView;
}
}