我有一个平面的产品文件,如下所示:
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中,我像So一样进行绑定:
<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>
我的Usercontrol的代码隐藏是
public GraphTreeView()
{
InitializeComponent();
MyTree.DataContext = new HierarchyViewModel();
}
但由于某种原因,树视图不会填充。我测试了Hierachy一代,它似乎按预期工作。我确信我的绑定中有一些错误,我很感激你帮助我搞清楚。 提前谢谢!
更新:使用Xavier的答案,我能够深入到: 美元 ---价格 - - 交换 最后一个级别仍然缺失。
更新2 经过一番争吵,并使用Snoop检查其绑定方式后,我“入侵”了答案。事实证明,绑定是(按预期)吐出一个没有ToString()方法定义的'Product'类列表。我覆盖了我的类定义中的那些,并使用ItemContainerStyle
作为资源来定义最后一个Binding。如果有人有兴趣,这是完整的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>
答案 0 :(得分:0)
确保将ItemsSource
本身的TreeView
设置为最外层的集合。此外,您需要将每个数据模板上的ItemsSource
属性设置为关联视图模型中的子集合。
例如:
<TreeView ItemsSource="{Binding Currency}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type xy:CurrencyViewModel}" ItemsSource="{Binding AssetTypes}">
<TextBlock Text="{Binding currency}"/>
</HierarchicalDataTemplate>
...
</TreeView.Resources>
</TreeView>
在ItemsSource
上设置TreeView
会启动流程以填充控件,然后为集合中的项目定义的数据模板将控制每个项目的呈现方式。
HiearchicalDataTemplate
的目的是通知每个子视图在哪里可以找到该类型的每个项目的子项目。因此,每个TreeViewItem
将使用关联模板的内容构建其视图,并使用ItemsSource
属性查找要为其创建自己的子视图的项集合。该过程将继续,直到生成整个树。