【问题标题】:Figuring Out Bindings for 4 level Tree View item in WPF找出 WPF 中 4 级树视图项的绑定
【发布时间】:2015-06-24 22:34:57
【问题描述】:

我有一个产品的平面文件,看起来像这样:

 public List<Product> Products = new List<Product>{
 new Product{Name = "OIS Swap", AssetType="Rates",ProductType="Swap",Currency="USD"},
 new Product{Name = "Libor Swap", AssetType ="Rates",ProductType="Swap",Currency="USD"},};

我想通过这样的分类来填充 WPF 中的 TreeView:

USD
--Rates
----Swap
------OIS Swap

首先,我使用 Linq 生成了一个 4 级层次结构,如下所示:

class HierarchyViewModel{
    public static IEnumerable<CurrencyViewModel> Currency {get;set;}
       public  HierarchyViewModel()
        {
            Currency = Products
                .OrderBy(prod => prod.Currency)
                .GroupBy(prod => prod.Currency)
                .OrderBy(group=> group.Key)
                .Select(group =>
                    new CurrencyViewModel(group.Key, group.Select(prod => prod).ToArray()
                        )
                        ).ToArray();

        }
    }

    class CurrencyViewModel
    {
        public string currency;
        public IEnumerable<AssetTypeViewModel> AssetTypes { get; set; } 

        public CurrencyViewModel(string currency, IEnumerable<Product> CurrencySorted)
        {
            this.currency = currency;
            AssetTypes = CurrencySorted
                         .OrderBy(prod => prod.AssetType)
                         .GroupBy(prod => prod.AssetType)
                         .OrderBy(group => group.Key)
                         .Select(group => new AssetTypeViewModel(group.Key, group.Select(prod => prod).ToArray()
                             )
                             ).ToArray();
        }
    }


    class AssetTypeViewModel
    {
       public string assettype;

       public IEnumerable<ProductTypeViewModel> ProductType { get; set; }

      public  AssetTypeViewModel(string assettype, IEnumerable<Product> AssetSorted)
       {
           this.assettype = assettype;
           ProductType = AssetSorted
               .OrderBy(prod => prod.ProductType)
               .GroupBy(prod => prod.ProductType)
               .OrderBy(group => group.Key)
               .Select(group => new ProductTypeViewModel(group.Key, group.Select(prod => prod).ToArray()
                   )
                   ).ToArray();
       }

    }

    class ProductTypeViewModel
    {
        string producttype;
        public IEnumerable<Product> Products;
        public ProductTypeViewModel(string producttype,IEnumerable<Product> ProductSorted)
        {
            this.producttype = producttype;
            Products = ProductSorted
                .OrderBy(prod => prod.ProductType)
                .Select(prod => prod).ToArray();
        }
    }

在我的 XAML 中,我执行如下绑定:

        <TreeView.Resources>
            <HierarchicalDataTemplate  DataType="{x:Type xy:CurrencyViewModel}" ItemsSource="{Binding currency}">
            <TextBlock Text="{Binding currency}"/>
            </HierarchicalDataTemplate>
            <HierarchicalDataTemplate  DataType="{x:Type xy:AssetTypeViewModel}" ItemsSource="{Binding assettype}">
                <TextBlock Text="{Binding assettype}"/>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate  DataType="{x:Type xy:ProductTypeViewModel}" ItemsSource="{Binding producttype}">
                <TextBlock Text="{Binding producttype}"/>
            </HierarchicalDataTemplate>
            <DataTemplate DataType="{x:Type xy:Product}" >
                <TextBlock Text="{Binding Name}"/>
            </DataTemplate>

        </TreeView.Resources>

    </TreeView>

我的用户控件的代码隐藏是

public GraphTreeView()
        {
            InitializeComponent();


            MyTree.DataContext = new HierarchyViewModel();
         }

但由于某种原因,树视图没有填充。我测试了 Hierachy 一代,它似乎按预期工作。我确信我的绑定中有一些错误,如果您能帮助我解决这个问题,我将不胜感激。 提前致谢!

更新:使用 Xavier 的回答,我能够深入了解: 美元 ---费率 - - 交换 最后一关还没有。

更新 2 经过一番争论,并使用 Snoop 检查其绑定方式,我“破解”了答案。结果,绑定(如预期的那样)吐出没有 ToString() 方法定义的“产品”类列表。我覆盖了我的类定义中的那些,并使用ItemContainerStyle 作为资源来定义最后一条绑定。如果有人感兴趣,这里是完整的 XAML。非常感谢 Xavier,他让我走上了正确的道路。

<UserControl.Resources>
        <xy:ProducttoNameConverter x:Key="ProductToNameConverter"/>
        <ItemContainerTemplate x:Key="LastLegConverter">          

            <TextBlock Text="{Binding}"/>

        </ItemContainerTemplate>

    </UserControl.Resources>
 <TreeView  x:Name="MyTree"  ItemsSource="{Binding Currency}"> 

            <TreeView.Resources>
                <HierarchicalDataTemplate DataType="{x:Type xy:CurrencyViewModel}" ItemsSource="{Binding AssetTypes }" >

                   <TextBlock Text="{Binding MyCurrency}"/>
                </HierarchicalDataTemplate>

                <HierarchicalDataTemplate DataType="{x:Type xy:AssetTypeViewModel}" ItemsSource="{Binding ProductType}">

                    <TextBlock Text="{Binding MyAssetType}"/>

                </HierarchicalDataTemplate>
                <HierarchicalDataTemplate DataType="{x:Type xy:ProductTypeViewModel}" ItemTemplate="{StaticResource LastLegConverter}" ItemsSource="{Binding Products}">
                    <TextBlock Text="{Binding MyProductType}"/>


                </HierarchicalDataTemplate>

                </TreeView.Resources>

【问题讨论】:

    标签: wpf mvvm data-binding treeview


    【解决方案1】:

    确保将TreeView 本身的ItemsSource 设置为最外层集合。此外,您需要将每个数据模板上的 ItemsSource 属性设置为关联视图模型中的子项集合。

    例如:

    <TreeView ItemsSource="{Binding Currency}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type xy:CurrencyViewModel}" ItemsSource="{Binding AssetTypes}">
                <TextBlock Text="{Binding currency}"/>
            </HierarchicalDataTemplate>
            ...
        </TreeView.Resources>
    </TreeView>
    

    TreeView 上设置ItemsSource 会启动填充控件的过程,然后为集合中的项目定义的数据模板控制每个项目的呈现方式。

    HiearchicalDataTemplate 的目的是通知每个子视图在哪里可以找到该类型每个项目的子项目。因此,每个TreeViewItem 都将使用相关模板的内容来构造其视图,并使用ItemsSource 属性来查找要为其创建自己的子视图的项目集合。该过程一直持续到生成整个树为止。

    【讨论】:

    • 谢谢,它似乎在前三个级别上工作,但最后一个级别是我面临问题的地方。我在最后一个 HierarchicalDataTemplate 中指定了一个 Itemtemplate。然后在其中设置一个带有 itemsource IEnumerable Products 的 DataTemplate 以显示带有 Product.Name 的 TextBox。它拒绝向下钻取。你会知道为什么会这样吗?
    • 嗯,这是因为 Last Hierarchical 数据模板,即 ProductTypeViewModel 没有子级。但它确实有一个我想提取的可枚举产品列表。
    猜你喜欢
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-10
    • 2011-07-14
    • 2010-12-26
    相关资源
    最近更新 更多