XAML绑定仅适用于数组的第一项?

时间:2018-04-12 22:18:24

标签: wpf xaml data-binding

我有一个自定义用户控件,它具有依赖属性,如下所示:

    public static readonly DependencyProperty PagesProperty =
        DependencyProperty.Register("Pages", typeof(IEnumerable<MyContentPage>), typeof(UC_ApplicationWindow),
            new PropertyMetadata(new List<MyContentPage>()));

    public IList<MyContentPage> Pages
    {
        get => (IList<MyContentPage>)GetValue(PagesProperty);
        set => SetValue(PagesProperty, value);
    }

我在另一个项目中使用这个:

<graphicElements:UC_ApplicationWindow>
        <graphicElements:UC_ApplicationWindow.Pages>
            <x:Array Type="{x:Type graphicElements:MyContentPage}">
                <graphicElements:MyContentPage>
                    <graphicElements:MyContentPage.Content>
                        <StackPanel>
                            <ContentControl DataContext="{Binding DataContext, ElementName=gd_Main}">
                                ...some content
                            </ContentControl>
                            ...other content
                        </StackPanel>
                    </graphicElements:MyContentPage.Content>
                </graphicElements:MyContentPage>
                <graphicElements:MyContentPage>
                    <graphicElements:MyContentPage.Content>
                        <StackPanel>
                            <ContentControl DataContext="{Binding DataContext, ElementName=gd_Main}">
                                ...some content
                            </ContentControl>
                            ...other content
                        </StackPanel>
                    </graphicElements:MyContentPage.Content>
                </graphicElements:MyContentPage>
            </x:Array>
        </graphicElements:UC_ApplicationWindow.Pages>            
    </graphicElements:UC_ApplicationWindow>

基本上在内容的一部分中,我试图从父网格(gd_Main)的上下文中提取DataContext,而不是传递给它的页面。我的ElementName绑定工作...对于数组中的第一个元素。对于数组中的所有其他元素,我得到了这个:

Cannot find source for binding with reference 'ElementName=gd_Main'. BindingExpression:Path=DataContext; DataItem=null; target element is 'ContentControl' (Name=''); target property is 'DataContext' (type 'Object')

我错过了什么?为什么它会正确绑定第一个项目而不是其他项目?有没有更好的方法来解决这个问题?

1 个答案:

答案 0 :(得分:0)

好的,我不确定这是否是最好的解决方案,但我让它发挥作用。我最终做的是基本上蛮力和手动设置datacontext。我在构造函数中创建了值作为可观察集合,并订阅了集合更改事件,如下所示:

        Pages = new ObservableCollection<MyContentPage>();
        ((ObservableCollection<MyContentPage>)Pages).CollectionChanged += UC_ApplicationWindow_CollectionChanged;

然后在集合更改事件中,我将各个项的数据上下文绑定到当前控件的数据上下文。这是方法:

    void UC_ApplicationWindow_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        foreach (MyContentPage pg in e.NewItems.OfType<MyContentPage>())
        {
            var bnd = new Binding(nameof(DataContext)) {Source = this};
            pg.Content.SetBinding(FrameworkElement.DataContextProperty, bnd);
        }
    }

请注意,我无法直接设置DataContext,因为在解析XAML时初始化时数据上下文尚未设置,加上它可能会稍后更改,所以我需要创建一个实际的绑定所以它正确更新。

另外值得注意的是。这基本上与@Shivani Katukota上面的评论做同样的事情,其中​​一个差异在我的情况下是相当重要的,但在其他情况下可能是无关紧要的。当项目被添加到集合中时,此方法在代码中绑定,在XAML中绑定意味着您必须在XAML中为每个项目执行此操作。我的控件旨在让其他用户在其他项目中使用它,因此必须在XAML中设置它需要我向用户提供该指令,如果他们没有这样做,它将无法正常工作。如果你在内部这样做,那么使用{x:Reference}并不是什么大事......