找出 WPF 中 4 级树视图项的绑定
Figuring Out Bindings for 4 level Tree View item in WPF
我有一个看起来像这样的产品的平面文件:
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 生成,它似乎按预期工作。我确定我的绑定中存在一些错误,非常感谢您帮助我解决问题。
提前致谢!
Update :使用 Xavier 的回答,我能够深入了解:
美元
---费率
- - 交换
还缺最后一关
更新 2 经过一番争论,并使用 Snoop 检查其绑定方式,我 'hacked' 进入了答案。事实证明,绑定 是 (如预期的那样)吐出一个没有 ToString() 方法定义的 'Product' classes 列表。我覆盖了我的 class 定义中的那些,并使用 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>
确保将 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
属性 来查找要为其创建自己的子视图的项目集合。该过程一直持续到生成整棵树。
我有一个看起来像这样的产品的平面文件:
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 生成,它似乎按预期工作。我确定我的绑定中存在一些错误,非常感谢您帮助我解决问题。 提前致谢!
Update :使用 Xavier 的回答,我能够深入了解: 美元 ---费率 - - 交换 还缺最后一关
更新 2 经过一番争论,并使用 Snoop 检查其绑定方式,我 'hacked' 进入了答案。事实证明,绑定 是 (如预期的那样)吐出一个没有 ToString() 方法定义的 'Product' classes 列表。我覆盖了我的 class 定义中的那些,并使用 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>
确保将 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
属性 来查找要为其创建自己的子视图的项目集合。该过程一直持续到生成整棵树。