【问题标题】:WPF - Advice on using a treeview style menu structureWPF - 关于使用树视图样式菜单结构的建议
【发布时间】:2019-01-30 06:06:10
【问题描述】:

我是 WPF 新手。我正在将一个 Win Forms 应用程序迁移到 WPF,这需要我大量学习。

在 WinForms 中,我会创建一个公共控件的子类(MyLabel:Label、MyDataGrid:DataGrid 等) 这将允许我设置所有我需要的属性和样式,并且这些对于我随后使用的任何控件都是一致的。此外,我可以在这些控件上实现可用于我的所有控件的功能。

我在 WPF 中使用 TreeView/TreeViewItem 做到这一点非常失败。 我用普通的 TreeView 创建了一个工作示例,然后在 MainPage 中简单地替换了 MyTreeView。我得到: System.InvalidOperationException: 'Items 集合在使用 ItemsSource 之前必须为空。'

希望您可以从此链接下载项目: https://app.box.com/s/9ofyuwfgk2cobqhokezgkknvtnmzmeq7

部分设计更改是将菜单实现为屏幕左侧的树形视图。这将有大约 60 个选项。

我花了一些时间,并有一个填充的 TreeView。 但是,我相信可以在这里使用菜单,并将其设置为树视图。这个对吗? 如果是这样,谁能给我举个例子,因为我在谷歌上找不到。 Google 似乎认为我想要 TreeView 上的上下文菜单。

编辑添加代码:

TreeView xaml(TreeViewItem 基本相同)

    <TreeView x:Class="WpfApp1.Controls.MyTreeView"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:local="clr-namespace:WpfApp1.Controls"
         mc:Ignorable="d"
         d:DesignHeight="450" d:DesignWidth="800">
        <Grid>
        </Grid>
    </TreeView>

树视图cs

    using System.Windows;
    using System.Windows.Controls;

    namespace WpfApp1.Controls
    {
        /// <summary>
        /// Interaction logic for MyTreeView.xaml
        /// </summary>
        public partial class MyTreeView : TreeView
        {
            public MyTreeView()
            {
                InitializeComponent();
            }

        protected override DependencyObject GetContainerForItemOverride()
        {
            return new MyTreeView();
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is MyTreeView;
        }
    }

主窗口

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        xmlns:Controls="clr-namespace:WpfApp1.Controls"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <XmlDataProvider x:Key="treeViewStructure" Source="Data/treeViewStructure.xml" XPath="./*/Category"/>

        <HierarchicalDataTemplate DataType="Category" ItemsSource="{Binding XPath=*}">
            <TextBlock Text="{Binding XPath=@Name}"/>
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate DataType="SubCategory" ItemsSource="{Binding XPath=*}">
            <TextBlock Text="{Binding XPath=@Name}"/>
        </HierarchicalDataTemplate>
    </Window.Resources>
    <Grid>
        <Controls:MyTreeView x:Name="mainTreeViewMenu"
                      Grid.Column="0"
                      BorderThickness="0"
                      ItemsSource="{Binding Mode=OneWay, Source={StaticResource treeViewStructure}}" DataContext="{DynamicResource treeViewStructure}"/>
    </Grid>
</Window>

将 Controls:MyTreeView 更改为简单的 TreeView 将使应用程序能够正常运行

ETA2:布拉德利的 XML:

  <?xml version="1.0" encoding="utf-8" ?>
  <Categories>
    <Category Name="1">
      <SubCategory Name="A"/>
      <SubCategory Name="B"/>
    </Category>
    <Category Name="2">
      <SubCategory Name="C"/>
      <SubCategory Name="D"/>
      <SubCategory Name="E"/>
      <SubCategory Name="F"/>
      <SubCategory Name="G"/>
      <SubCategory Name="H"/>
    </Category>
    <Category Name="3">
      <SubCategory Name="I"/>
      <SubCategory Name="J"/>
    </Category>
    <Category Name="4">
      <SubCategory Name="K"/>
      <SubCategory Name="L"/>
    </Category>
  </Categories>

【问题讨论】:

  • 这是因为“menu”类通常用于上下文菜单。您不会使用一个来替换树视图。另外,请在此处发布相关代码。我们无法为您提供帮助
  • 感谢您的回复。我在这里找到了一篇文章(现在找不到),建议将菜单样式设置为树视图,而不是尝试将树视图用作菜单。现在直接添加代码。
  • 像这样在树视图上设置数据上下文是非常奇怪的。我会尝试删除它。除此之外,我没有看到您的异常的明显来源。
  • 您正在添加一个 &lt;Grid&gt; 作为 TreeView 的子控件,并且添加一个空控件。这就是你的异常的根源,你想达到什么目的?
  • 还请记住,WPF 是专门设计的,因此很少需要子类化 Windows 控件。 Matthew McDonalds 的优秀著作《Pro WPF in C#》中有这样一段话:“在以前的 Windows 开发框架中,自定义控件发挥了核心作用。但是在 WPF 中,重点已经转移。自定义控件仍然是构建自定义小部件的有用方法,您可以在应用程序之间共享,但当您想要增强和自定义核心控件时,它们不再是必需的.....

标签: c# wpf


【解决方案1】:

您的代码中有一些错误,但您已经接近了。要记住的是,当您将 XML 数据序列化为特定类型的类时,会使用像 DataType 这样的东西。当您使用 XmlDataProvider 时,您不会获得此好处,所有数据都被序列化为通用 XML 数据类,因此您必须做的事情与您在网上找到的大多数示例 TreeView 代码稍有不同。

在您的情况下,您需要将所有根元素专门绑定到您使用键声明的HierarchicalDataTemplate 资源,然后再次通过 XPath 将其绑定到子列表。这应该做到这一点:

<Window.Resources>

    <XmlDataProvider x:Key="treeViewStructure" Source="Data/treeViewStructure.xml" />

    <HierarchicalDataTemplate x:Key="SubCategory">
        <TextBlock Text="{Binding XPath=@Name}" />
    </HierarchicalDataTemplate>

    <HierarchicalDataTemplate x:Key="Category" ItemsSource="{Binding XPath=SubCategory}" ItemTemplate="{StaticResource SubCategory}">
        <TextBlock Text="{Binding XPath=@Name}" />
    </HierarchicalDataTemplate>

    <!-- force all treeviewitems to be initially expanded -->
    <Style TargetType="{x:Type TreeViewItem}">
        <Setter Property="IsExpanded" Value="True" />
    </Style>

</Window.Resources>

<TreeView
    ItemsSource="{Binding Source={StaticResource treeViewStructure}, XPath=/Categories/Category}"
    ItemTemplate="{StaticResource Category}" />

结果:

此外,如果您没有明确需要每个节点使用不同的模板,那么您可以只使用一个,WPF 会发现您的孩子自己没有孩子:

<HierarchicalDataTemplate x:Key="Category" ItemsSource="{Binding XPath=SubCategory}" >
    <TextBlock Text="{Binding XPath=@Name}" />
</HierarchicalDataTemplate>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多