gpt4 book ai didi

WPF DataTemplates - 为什么呈现不同?

转载 作者:行者123 更新时间:2023-12-03 10:21:49 28 4
gpt4 key购买 nike

我为自己设计的一个非常基本的 WPF 练习遇到了一个奇怪的问题,即从 ViewModel 动态填充菜单。给定以下主窗口标记:

<Window x:Class="Demosne.Client.WPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525"
xmlns:project="clr-namespace:Demosne.Client.WPF">
<Grid>
<Menu Height="26" Name="menu1" VerticalAlignment="Top" HorizontalAlignment="Stretch" ItemsSource="{Binding MainMenuItems}">
<Menu.ItemTemplate>
<HierarchicalDataTemplate >
<MenuItem Header="{Binding Text, Mode=OneTime}" ItemsSource="{Binding MenuItems}"/>
</HierarchicalDataTemplate>
</Menu.ItemTemplate>
<!--<MenuItem Header="File" />
<MenuItem Header="Edit" />-->
</Menu>
</Grid>

和 View 模型:
public class MainWindowViewModel
{
private IList<MenuItemViewModel> _menuItems = new List<MenuItemViewModel>()
{
new MenuItemViewModel() { Text = "File" },
new MenuItemViewModel() { Text = "Edit" }
};

public IList<MenuItemViewModel> MainMenuItems
{
get
{
return _menuItems;
}
}
}

public class MenuItemViewModel
{
public string Text { get; set; }

public IList<MenuItemViewModel> MenuItems
{
get
{
return _menuItems;
}
}

private IList<MenuItemViewModel> _menuItems = new List<MenuItemViewModel>();
}

我希望 GUI 能够准确地再现标记中两个注释掉的行的结果 - 两个 MenuItems 称为 File 和 Edit。

但是,绑定(bind)版本在鼠标悬停时表现异常:

标记版本:

enter image description here

绑定(bind)版本:

enter image description here

为什么它们不同?

最佳答案

你得到了有趣的结果,因为你没有真正使用 HierarchicalDataTemplate正确的方法。

当您在 Menu 上设置 itemssource 时,它​​将为集合中的每个对象创建一个 MenuItem,如果您还提供 HierarchicalDataTemplate使用 itemssource 集,它还将为该集合中的每个子对象创建 MenuItems,沿着层次结构。

在您的情况下,您自己在模板中添加了一个 MenuItem,这不是必需的。框架为您隐式创建这些项目。这导致菜单行为异常。

因此,要获得正确的结果,您应该执行以下操作:

<HierarchicalDataTemplate ItemsSource="{Binding MenuItems}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Text}" />
</StackPanel>
</HierarchicalDataTemplate>

更新
通过在某物上设置 DataTemplate,您就是在告诉 WPF 您想要控制其每个项目的显示方式。

在这种情况下, HierarchicalDataTemplate使用,这是一个用于生成带标题的控件的模板。这种控件包含一个标题和一个项目集合。

当您将此类模板应用于对象时,您在模板中放入的任何内容都将用作标题,并且将通过将模板应用于集合集中的每个子对象作为 ItemsSource 来创建项目集合模板。因此它将递归地将模板应用于层次结构中的所有对象。

在您的示例中,您有一个菜单。您可以通过这样做来创建它:
<Menu ItemsSource="{Binding MainMenuItems}" />

它可以正常工作,但是由于您没有应用模板,为了告诉它应该如何显示集合中的项目,它只会为 itemssource 中的每个对象创建一个 MenuItem 并调用 ToString()在上面。然后,此值将用作 MenuItem 的 Header 属性。

由于这不是您想要的,您必须应用一个模板来告诉 WPF 您希望在隐式生成的 MenuItem 的标题中显示什么内容。

在我的示例中,我只是制作了一个包含 TextBlock 的模板,该模板绑定(bind)到 viewmodel 上的 Text 属性。

更新 2
如果您现在想在隐式创建的菜单项上设置属性,您必须通过设置 ItemContainerStyle 来实现。 HierarchicalDataTemplate 上的属性(property).此处定义的样式将应用于所有生成的菜单项。

因此,要将 MenuItem 的 Command 属性绑定(bind)到 viewmodel 上的 Command 属性,您可以执行以下操作:
<HierarchicalDataTemplate.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Command"
Value="{Binding Command}" />
</Style>
</HierarchicalDataTemplate.ItemContainerStyle>

关于WPF DataTemplates - 为什么呈现不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13539942/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com