【问题标题】:XAML Binding only works on first item of array?XAML 绑定仅适用于数组的第一项?
【发布时间】:2018-04-17 06:11:14
【问题描述】:

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

    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')

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

【问题讨论】:

  • 我不完全确定,但名称范围可能存在问题。要解决此问题,您可以尝试使用 Source={x:Reference gd_Main} 而不是 ElementName
  • 嗯,嗯,这有点工作......我试图绑定的元素在 gd_Main 内部,所以当我将它更改为引用时,它会给我循环引用错误。我在 gd_Main 内创建了一个虚拟网格(因此它是包含我要绑定的控件的顶级元素的同级元素)并将名称移到该网格中。这行得通,它得到了正确的上下文,但它似乎非常笨拙......似乎必须有更好的方法。

标签: wpf xaml data-binding


【解决方案1】:

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

        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}...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-12-08
    • 2012-04-09
    • 1970-01-01
    • 2013-10-28
    • 2016-10-15
    • 2021-02-10
    • 2021-02-12
    相关资源
    最近更新 更多