我有一个自定义用户控件,它具有依赖属性,如下所示:
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')
我错过了什么?为什么它会正确绑定第一个项目而不是其他项目?有没有更好的方法来解决这个问题?
答案 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}并不是什么大事......