绑定到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在属性变为非空时注意到?

+0

当'DataContext'发生变化时,是否为''viewModel''激发'PropertyChanged'? – user7116 2013-02-15 20:38:53

+0

尝试用'Path = DataContext.items'重置'Path = viewModel.items'。 – 2013-02-15 21:06:09

+0

“当DataContext更改时,是否为”viewModel“触发PropertyChanged?” - DataContext不会更改。它在UserControl的构造函数中设置并且永远不会改变。 – 2013-02-15 21:19:34

当我想在我的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>(); 
+0

如果在使用usercontrol时使用XAML指定了ax:Name,那么可能会覆盖Name:但是在一个快速测试中,似乎没有 – 2013-02-15 22:48:56

+0

在RadDataForm的上下文中使用{Binding Path = items}会绑定到RadDataForm的DataContext中的一个属性,这与我的UserControl的DataContext不一样。 – 2013-02-15 22:54:18

+0

你说“表单的ItemsSource绑定到UserControl的ViewModel上的一个属性“,我认为它们共享相同的数据上下文。我错过了什么? – 2013-02-15 23:02:51