【发布时间】:2019-11-01 16:40:35
【问题描述】:
我想要一个有条件的 XAML 来选择是 TreeView.Resources 还是其他。
我正在使用MaterialDesignInXAML toolkit 的Card,里面是TreeView。
假设我有一个 Fruits 集合,其中包含另一个名为 Trees 的集合。
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type domain:Tree}" ItemsSource="{Binding Fruits}">
// tree information here ...
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type domain:Fruit}">
// fruit information here ...
</DataTemplate>
</TreeView.Resources>
这里的问题是,有些水果不是从树上长出来的。所以我想要的是拥有另一个资源,但仍然会继续使用模板。
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type domain:Fruit}">
// fruit information here
</HierarchicalDataTemplate>
</TreeView.Resources>
我希望我的输出如下所示:
> Apple Tree
- Apples
> Mango Tree
- Mangoes
> Watermelon
编辑:
我使用了 @BionicCode 的第二个建议,即使用DataTemplateSelector。我将此添加到我的 XAML:
<UserControl DataContext="{Binding ViewModel}">
<UserControl.Resources>
<domain:DtmSelector x:Key="DtmSelector">
<domain:DtmSelector.WithTree>
<HierarchicalDataTemplate DataType="{x:Type domain:Tree}" ItemsSource="{Binding Fruits}">
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate DataType="{x:Type domain:Fruit}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</domain:DtmSelector.WithTree>
<domain:DtmSelector.WithoutTree>
<DataTemplate DataType="{x:Type domain:Tree}">
<TextBlock Text="{Binding Fruits[0].Name}"/>
</DataTemplate>
</domain:DtmSelector.WithoutTree>
</domain:DtmSelector>
</UserControl.Resources>
<TreeView
ItemsSource="{Binding Trees}"
ItemTemplateSelector="{StaticResource DtmSelector}"
/>
</UserControl>
在我的DtmSelector.cs中:
public class DtmSelector: DataTemplateSelector
{
public DataTemplate WithTrees { get; set; }
public DataTemplate WithoutTrees { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
Tree key = item as Tree;
if (key.Fruits.Count() == 0)
{
return WithTrees;
}
else
{
if (key.Fruits.Select(c=>c.Name).Contains(key.Name))
{
return WithTrees;
}
else
{
return WithoutTrees;
}
}
}
}
我ViewModel的概念是这样的:
foreach (var item in fruits)
{
if ( item.Tree == null)
{
if (!Trees.Select(c => c.Name).Contains(item.Name))
{
Trees.Add(new Tree(item.Name));
}
foreach (var tree in Trees.ToList())
{
if (tree.Name == item.Name)
{
tree.Fruits.Add(item);
}
}
}
else
{
if (!Trees.Select(c => c.Name).Contains(item.Tree.Name))
{
Trees.Add(item.Tree);
}
foreach (var tree in Trees.ToList())
{
if (tree.Name == item.Tree.Name)
{
tree.Fruits.Add(item);
}
}
}
}
问题
这组代码将首先检查Trees,而不添加Fruits。所以这条线if (key.Fruits.Count() == 0) 将永远返回true。有什么我可以做的吗?我错过了什么吗?
我发现 an answer from another thread 可能会有所帮助,但是,我不知道这将如何在 ViewModel 上工作,我不知道如何通过绑定的 Property 选择某个设置器。
【问题讨论】:
-
到底想达到什么目的?为了在
Style或Template之间切换,您可以使用StyleSelector或DataTemplateSelector。在大多数情况下,Trigger或DataTrigger也可以使用。 -
@BionicCode,我想使用条件语句在
TreeView.Resources中使用不同的ItemSource。 -
请更具体。你的
ItemsSource是什么?条件是什么?最常见的场景是绑定到视图模型。如果是这种情况并且条件与 UI 无关,那么您只需直接在视图模型中将不同的集合分配给源属性。如果条件与 UI 相关(例如,按下按钮),您可以使用ICommand来触发源属性的所述重新分配,或者使用DataTrigger。我不能给你一个例子,因为你的问题非常广泛。它缺乏细节。细节会影响最佳方法。 -
@BionicCode,请查看更新后的问题。
-
谢谢。您的问题是一个很好的例子,说明提供更多细节将如何导致不同的解决方案,因为许多假设都被消除了。此外,更多细节表明您最初的方法或策略是错误的。我发布了一个答案。