绑定到ViewModel中最初的NULL属性不会重新绑定
我有一个包含Telerik RadDataForm的UserControl。表单的ItemsSource绑定到属性上的用户控件的视图模型:绑定到ViewModel中最初的NULL属性不会重新绑定
<telerik:RadDataForm
ItemsSource="{Binding Path=viewModel.items, RelativeSource={RelativeSource AncesterType=local:MyUserControl}}"
/>
其中视图模型是:
public partial class MyUserControl: UserControl
{
public MyUserControlVM viewModel
{ get { return this.DataContext as MyUserControlVM; } }
}
内视图模型,项目是一个相当普通的集合:
public class MyUserControlVM : MyViewModelBase
{
private ObservableCollection<AnItem> items_;
public ObservableCollection<AnItem> items
{
get { return this.items_; }
set
{
this.items_ = value;
notifyPropertyChanged("items");
}
}
...
}
而且当然,MyViewModelBase实现INotifyPropertyChanged。
用户控件有一个项目依赖属性,当它被设置,它设置在视图模型匹配性质:
public partial class MyUserControl : UserControl
{
public ObservableCollection<AnItem> items
{
get { return GetValue itemsProperty as ObservableCollection<AnItem>; }
set { SetValue(itemsProperty, value); }
}
public static readonly DependencyProperty itemsProperty =
DependencyProperty.Register("items",
typeof(ObservableCollection<AnItem>),
typeof(MyUserControl), new PropertyMetadata(
new PropertyChangedCallback(itemsPropertyChanged)));
private static void itemsPropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
MyUserControl myUserControl = d as MyUserControl;
ObservableCollection<AnItem> items =
e.NewValue as ObservableCollection<AnItem>;
if (myUserControl != null && myUserControl.viewModel != null)
myUserControl.viewModel.items = items;
}
}
所有这一切似乎非常简单,如果有点乏味。
问题是MyUserControl上的项目依赖项属性绑定到另一个集合的当前项目的属性,并且当前项目最初为空,所以当MyUserControl最初加载时,其项目属性为null。因此,与RadDataForm绑定的MyUserControlVM上的items属性也是如此。
稍后,当该外部集合中的项目变为当前项时,将设置MyUserControl上的项目依赖项属性,并设置MyUserControlVM上的项目属性。 MyUserControlVM调用notifyPropertyChanged,这样监听器会被告知这个改变。但这最后一个不起作用。
之后,如果我检查RadDataForm,它的ItemsSource属性仍然为空。
这就好像RadDataForm没有监听propertychanged事件,因为它绑定的内容最初是空的。在开始时绑定属性不为空的类似情况下,此模式可以正常工作,因为当前项目从一个项目更改为另一个项目,但似乎无法从没有当前项目变为有效项目。
那么,有关如何使这项工作的任何想法?根据具体情况,我不能在表单加载时使项目始终具有值 - 在开始时它总是为空。如何让RadDataForm在属性变为非空时注意到?
当我想在我的UserControl
(例如自定义属性,或者在您的情况下,DataContext
)的根目录引用某些内容时,我通常会给我的UserControl一个Name
。然后,我使用此名称和Binding
上的ElementName属性进行设置。
<UserControl
...
Name="TheControl">
<Grid>
<TextBlock Text={Binding Path=DataContext.items, ElementName=TheControl}" />
</Grid>
</UserControl>
由于viewModel
属性,你可以使用和DataContext
互换。
但是,在你的情况下它可能实际上更简单。首先,您的代码中存在拼写错误。它应该是AncestorType
(带有'o')。其次,您可能想尝试仅使用{Binding Path=items}
设置绑定,因为我相信您的控件已经继承了正确的DataContext
。 (不知道最后一个,但。)
如果问题仍然存在,并且怀疑它其实有事情做与items
的财产返还null
最初,你总是可以用一个空的集合初始化items_
避免null
。
private ObservableCollection<AnItem> items_ = new ObservableCollection<AnItem>();
如果在使用usercontrol时使用XAML指定了ax:Name,那么可能会覆盖Name:但是在一个快速测试中,似乎没有 – 2013-02-15 22:48:56
在RadDataForm的上下文中使用{Binding Path = items}会绑定到RadDataForm的DataContext中的一个属性,这与我的UserControl的DataContext不一样。 – 2013-02-15 22:54:18
你说“表单的ItemsSource绑定到UserControl的ViewModel上的一个属性“,我认为它们共享相同的数据上下文。我错过了什么? – 2013-02-15 23:02:51
当'DataContext'发生变化时,是否为''viewModel''激发'PropertyChanged'? – user7116 2013-02-15 20:38:53
尝试用'Path = DataContext.items'重置'Path = viewModel.items'。 – 2013-02-15 21:06:09
“当DataContext更改时,是否为”viewModel“触发PropertyChanged?” - DataContext不会更改。它在UserControl的构造函数中设置并且永远不会改变。 – 2013-02-15 21:19:34