我正在尝试编写一个程序,其中一部分将显示一个打开的窗口列表(或更具体地说,它们的名称或标题)
因此视图的XAML如下所示:
<Window.DataContext>
<local:ViewModel />
</Window.DataContext>
<ItemsControl ItemsSource="{Binding Windows}" />
并且ViewModel
类看起来像这样:
public ObservableCollection<Window> Windows { get; set; }
public ViewModel()
{
this.Windows = new ObservableCollection<Window>();
this.Windows.Add(new Window());
}
这会导致程序(和设计器视图)抛出InvalidOperationException: Window must be the root of the tree. Cannot add Window as a child of Visual.
问题似乎是ItemsControl
认为我实际上想要将Window
本身作为一个控件添加而不是作为一个类(我期望窗口显示文本{{ 1}}或类似的东西)。
我尝试添加System.Windows.Window
,但这似乎有相同的结果。
最后,我尝试使用<ItemsControl.ItemTemplate><DataTemplate>...
的单个公共属性创建一个虚拟WindowHolder
类。这似乎有效,但似乎是一种非常不优雅的做事方式,感觉应该更简单。
问题是“你怎么能简单地(最好是在XAML中)在WPF上显示一个窗口标题列表Window
,绑定到视图模型中的ItemsControl
?
答案 0 :(得分:2)
您可以使用ListBox
代替ItemsControl
<ListBox ItemsSource="{Binding Windows}">
<ListBox.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent" />
<SolidColorBrush x:Key="{x:Static SystemColors.HighlightTextBrushKey}" Color="Black" />
<SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="Transparent" />
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
问题是,将控件添加到通用ItemsControl
中的默认行为会导致ContentPresenter
包含在控件本身中。因此,您的集合Windows
将希望作为容器添加到ItemsControl
的{{1}},但由于异常中描述的原因而失败。 ItemsPresenter
有效,因为包装容器为ListBox
,而不是ListBoxItems
。为了在Windows
中为Window
提供支持,您必须为ItemsControl
实现自己的自定义控件,以返回不是ItemsControl
的容器。
答案 1 :(得分:1)
我怀疑你已经有了最好的方法 - 听起来像WPF不喜欢填充ItemsControl
并引用已经存在于可视树上的元素。
可视化树必须检查引用,因为我已经通过创建一个包装类来测试它,该类包含对Window
的引用,然后使用ItemsControl
来显示该窗口的内容(到看看我是否可以让它爆炸!)并且它给出了以下错误:
Logical tree depth exceeded while traversing the tree. This could indicate a cycle in the tree.
这是一个无限递归的树
总而言之,最简单的解决方案似乎是为您想要的属性(您已经完成)创建一个包装器,并避免引用叶子节点中的祖先元素!
答案 2 :(得分:0)
您的想法是正确的,您需要为ItemsControl创建一个ItemTemplate。 ItemsControl中的每个项目都是Type Window,您需要在模板中公开Title属性
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text={Binding Title}/>
</DataTemplate>
</ItemsControl.ItemTemplate>
答案 3 :(得分:0)
我要做的是以下内容: