0

我有一个包含 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; } }
}

在视图模型中,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。

用户控件有一个项目依赖属性,当它被设置时,它会在视图模型上设置匹配属性:

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 上的项目属性。MyUserControlVM 调用 notifyPropertyChanged 以便将更改通知侦听器。但这最后一个不起作用。

之后,如果我检查 RadDataForm,它的 ItemsSource 属性仍然为空。

就像 RadDataForm 没有监听 propertychanged 事件,因为它最初绑定的是 null。在绑定属性在开始时不为空的类似情况下,当当前项目从一个项目更改为另一个项目时,此模式可以正常工作,但从没有当前项目到有一个项目似乎不起作用。

那么,关于如何进行这项工作的任何想法?在这种情况下,我不能让项目在表单加载时始终具有值 - 一开始它总是为空。当属性变为非空时,如何让 RadDataForm 注意到?

4

1 回答 1

0

当我想在我的根目录引用某些东西UserControl(例如,自定义属性,或者在你的情况下,DataContext),我通常给我的 UserControl 一个Name. 然后我将此名称与 ElementName 属性一起使用Binding来设置它。

<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>();
于 2013-02-15T22:22:29.623 回答