将TreeView转换为多个ListBoxes

时间:2014-03-05 10:51:08

标签: c# wpf mvvm listbox treeview

给定表单的分层数据结构:

public class MyData
{
    public string Description { get; set; }
    public IEnumerable<MyData> SubNodes { get; set; } 
}

我想显示一系列表示该结构的ListBoxes。应保留流程 - &gt;正确(例如像OS X的Finder),其中最左侧的ListBox包含根节点,最右侧包含子节点。

每个ListBox中的多个项目应该是可选的,这会导致后续ListBox中的可用项目更新。这对于一些LINQ和一个硬编码的ListBox来说是微不足道的,但我希望模板是动态的(即根据项目的可用性添加和删除ListBoxes)。我也希望解决方案与MVVM兼容。

这种类型的控件可能已经捆绑在WPF中,但是我不确定要搜索什么!任何指针都会受到赞赏。

1 个答案:

答案 0 :(得分:0)

首先,您不需要使用LINQ(或任何C#代码!)来在下一个ListBox上设置ItemSource。您可以使用WPF数据绑定:

    <ListBox x:Name="listbox1" ItemsSource="{Binding Path=YourDataCollection}"/>
    <ListBox x:Name="listbox2" ItemsSource="{Binding ElementName=listbox1, Path=SelectedItem.SubNodes}" />
    <ListBox x:Name="listbox3" ItemsSource="{Binding ElementName=listbox2, Path=SelectedItem.SubNodes}" />

基本上你将下一个列表框绑定到前一个列表框的SelectedItem的子节点(你可能应该确保列表框一次只能选择一个)

现在要隐藏没有任何项目的列表框,可以使用IValueConverter将对象转换为可见性状态。为此,请创建一个类:

public class ObjectToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
            return Visibility.Visible;
        else
            return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

并在列表框中添加更多数据绑定:

<Window.Resources>
    <local:ObjectToVisibilityConverter x:Key="objectToVisible" />
</Window.Resources>
<Grid>
    <ListBox x:Name="listbox1" ItemsSource="{Binding ElementName=mw1, Path=dataCollection}"/>
    <ListBox x:Name="listbox2" ItemsSource="{Binding ElementName=listbox1, Path=SelectedItem.SubNodes}" 
    Visibility="{Binding ElementName=listbox2, Path=ItemsSource, Converter={StaticResource objectToVisible}}" />
    <ListBox x:Name="listbox3" ItemsSource="{Binding ElementName=listbox2, Path=SelectedItem.SubNodes}" 
    Visibility="{Binding ElementName=listbox3, Path=ItemsSource, Converter={StaticResource objectToVisible}}" />
</Grid>

确保将您的命名空间添加到窗口中,因此实际上可以找到valueconverter,在我的情况下我添加了这个:

xmlns:local="clr-namespace:WpfApplication1"

现在这个解决方案仅适用于固定数量的列表框,但除了valueconverter之外,它不依赖于任何C#代码。你真的不知道你可能需要多少个子级别吗?例如,您可以使用此技术将数十个列表框添加到scrollview。 实际上在UserControl中使这个动态变得非常痛苦,因为当选择不同的根节点时,添加列表框,设置项目,删除或隐藏列表框会涉及大量代码。

另一种可能性是为TreeView创建HierarchicalDataTemplate以自定义树视图的外观。这样可以保留树视图,因为它是分层数据最有用的控件,但是使用WPF及其模板完全可以改变它的外观。您可能需要更改treeview的controltemplate(我建议使用Blend编辑任何类型的WPF模板)