我有一个包含Telerik RadDataForm的UserControl。表单的ItemsSource绑定到UserControl的ViewModel上的属性:
<telerik:RadDataForm
ItemsSource="{Binding Path=viewModel.items, RelativeSource={RelativeSource AncesterType=local:MyUserControl}}"
/>
viewModel是:
public partial class MyUserControl: UserControl
{
public MyUserControlVM viewModel
{ get { return this.DataContext as MyUserControlVM; } }
}
在viewmodel中,items是一个相当普通的集合:
public class MyUserControlVM : MyViewModelBase
{
private ObservableCollection<AnItem> items_;
public ObservableCollection<AnItem> items
{
get { return this.items_; }
set
{
this.items_ = value;
notifyPropertyChanged("items");
}
}
...
}
当然,MyViewModelBase实现了INotifyPropertyChanged。
用户控件有一个items依赖项属性,当它设置时,它会在视图模型上设置匹配属性:
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上的items依赖项属性绑定到另一个集合的当前项的属性,并且当前项最初为null,因此当最初加载MyUserControl时,其items属性为null。因此,RadDataForm绑定到的MyUserControlVM上的items属性也是如此。
稍后,当该外部集合中的项目成为当前项时,将设置MyUserControl上的项依赖项属性,并在MyUserControlVM上设置items属性。并且MyUserControlVM调用notifyPropertyChanged,以便将侦听器通知更改。但这最后一次没有用。
之后,如果我检查RadDataForm,它的ItemsSource属性仍为null。
就像RadDataForm没有监听propertychanged事件一样,因为它绑定的内容最初为null。在绑定属性在开始时不为null的类似情况下,此模式在当前项目从一个项目更改为另一个项目时工作正常,但似乎无法使当前项目没有项目。
那么,关于如何使这项工作的任何想法?考虑到这种情况,我不能这样做,以便在表单加载时项目总是有一个值 - 它在开始时总是为空。当属性变为非空时,如何让RadDataForm注意到?
答案 0 :(得分:0)
当我想在我的UserControl
(例如自定义属性,或者像你的情况,DataContext
)的根目录中引用某些东西时,我通常会给我的UserControl一个{{1 }}。然后我将此名称与Name
上的ElementName属性一起使用来设置它。
Binding
由于<UserControl
...
Name="TheControl">
<Grid>
<TextBlock Text={Binding Path=DataContext.items, ElementName=TheControl}" />
</Grid>
</UserControl>
属性,您可以互换使用它和viewModel
。
然而,在您的情况下,它可能实际上更简单。首先,你的代码中有一个拼写错误。它应该是DataContext
(带有'o')。其次,您可能只想尝试使用AncestorType
设置绑定,因为我相信您的控件已经继承了正确的{Binding Path=items}
。 (但不确定最后一个。)
如果问题仍然存在,并且您怀疑它确实与最初返回DataContext
的{{1}}属性有关,那么您始终可以使用空集合初始化items
避免null
。
items_