ContentControl中的绑定崩溃问题

13

有没有人能告诉我为什么这会导致我的应用程序崩溃?似乎存在一些无限递归,但我无法弄清楚原因。我遇到了这个异常

在遍历树时超出了逻辑树深度。这可能表示树中存在循环

<ContentControl Content="{Binding}">
    <ContentControl.ContentTemplate>
        <DataTemplate>
            <Button Content="{Binding MyString}"/>
        </DataTemplate>
    </ContentControl.ContentTemplate>
</ContentControl>

这就是我全部的来源

    public MainWindow()
    {
        InitializeComponent();
        MyString = "Test";
        this.DataContext = this;
    }

    public string MyString { get; set; }
3个回答

20

您将MainWindow用作MainWindow内容的DataContext。当您在ContentControl上设置Content = "{Binding}"时,这会将ContentControl的内容设置为MainWindow实例。这是一个问题,因为ContentControl包含在MainWindow的Content中。每当Content属性接收到UIElement时,它会将其呈现为UIElement,而不是通过DataTemplate呈现非UI类。因此,您的树最终变成:

MainWindow
 ContentControl
  MainWindow
   ContentControl
    ...

使用一个单独的数据对象作为您的DataContext,而不是窗口本身,将会给您所需要的行为:

public partial class Window13 : Window
{
    public Window13()
    {
        InitializeComponent();
        MyData data = new MyData();
        data.MyString = "Test";
        this.DataContext = data;
    }
}

public class MyData
{
    public string MyString { get; set; }
}

1
John,你太棒了!!非常好用 :) 我终于可以把这个问题解决了,而且还知道了原因,多亏了你非常清晰的解释!谢谢并祝圣诞快乐。 - ImJames

3
尽管我完全同意被接受的答案,即您不应该这样做,但有时您确实没有选择。例如,我正在使用Xceed PropertyGrid,并且网格每个项目的DataContext是一个PropertyItem,它是一个包含实际数据的Value成员的UIElement

我找到的解决方法是使用ContentPresenter而不是ContentControl。文档并不清楚,但似乎UIElement是模板化的,而不是直接使用。

<ContentPresenter Content="{Binding}">
    <ContentPresenter.ContentTemplate>
        <DataTemplate>
            <Button Content="{Binding MyString}"/>
        </DataTemplate>
    </ContentPresenter.ContentTemplate>
</ContentPresenter>

0
你应该移除 ContentControl 的 Content 属性的绑定。这个属性本来是用来做什么的?

我对ContentControl的理解是,DataTemplate内的DataContext是ContentControl的内容,而不是DataContext。因此,如果我将其删除,则在DataTemplate中没有要绑定的DataContext。有什么想法吗? - ImJames

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接