WPF Treeview绑定两种或多种类型的数据

时间:2014-02-02 17:18:53

标签: c# wpf binding treeview treeviewitem

我想将两个或更多类数据绑定为 TreeViewItem 。 对于直接示例:文件和文件夹包含在另一个文件夹中,但您最初不知道结构。我想用WPF treeview实现它。但是treeview只能用 HierarchicalDataTemplate (例如我的代码)绑定一种类型的节点。

<DockPanel SizeChanged="FrameworkElement_OnSizeChanged">
    <DockPanel.Resources>
        <HierarchicalDataTemplate x:Key="NodeDataTemplate" 
                                  DataType="{x:Type sideList:SideListNode}" 
                                  ItemsSource="{Binding Path=Children}">

            <StackPanel Orientation="Horizontal">
                <TextBlock VerticalAlignment="Center" x:Name="DisplayName"  Text="{Binding DisplayName}" ></TextBlock>
            </StackPanel>
            <HierarchicalDataTemplate.Triggers>
                <DataTrigger Binding="{Binding Path=}" Value="0">
                    <Setter TargetName="DisplayName" Property="Background" Value="Red">
                    </Setter>
                </DataTrigger>
            </HierarchicalDataTemplate.Triggers>
        </HierarchicalDataTemplate>
    </DockPanel.Resources>

    <TreeView  
        x:Name="SideList" DockPanel.Dock="Left"  MinWidth="200" MaxWidth="250"  Background="Aqua"
              ItemTemplate="{StaticResource NodeDataTemplate}">

    </TreeView>

但当然文件夹和文件之间有一些不同。一些distingct属性为彼此。现在我们需要为创建节点绑定两种类型。一个用于文件,一个用于文件夹。我们怎么做到这一点?

2 个答案:

答案 0 :(得分:1)

所有可能的类都可以来自诸如

之类的接口
public Interface IGeneralInfo
{
    string info1{get;}
    string info2{get;}
    string info3{get;}
}

然后绑定到接口类型

修改

这里是我可以做的更详细的实际数据

MainWindow.XAML中的

<Window x:Class="DUALBIND.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <StackPanel>
        <Button x:Name="button1" Click="button1_Click" Content="ADD (this is set up for you to test)" FontFamily="Courier New" FontSize="16"/>
    <ListBox ItemsSource="{Binding}" x:Name="infolist">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Info1}"/>
                        <TextBlock Text=" :: "/>
                        <TextBlock Text="{Binding Info2}"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>

    </ListBox>
    </StackPanel>
</Grid>
</Window>
MainWindows.XAML.cs中的

(没有花时间从项目中删除使用)

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;//<-------- notice this
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace DUALBIND
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    static Random r = new Random();//best use of random

    ObservableCollection<IGeneralInfo> generalinfo = new ObservableCollection<IGeneralInfo>();
    public MainWindow()
    {
        InitializeComponent();

        infolist.DataContext = generalinfo;

        generalinfo.Add(new OBJA());
        generalinfo.Add(new OBJA());
        generalinfo.Add(new OBJA());
        generalinfo.Add(new OBJB(7));
        generalinfo.Add(new OBJB(6));
        generalinfo.Add(new OBJB(12345));

    }

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        /*this was set up for you to play with*/           

        MessageBox.Show("You get to mess with this");
        generalinfo.Add(new OBJB(MainWindow.r.Next()));
    }
}
}

在IGeneralInfo.cs

using System;

namespace DUALBIND
{
interface IGeneralInfo
{

    string Info1 {get; }
    string Info2 { get; }
}

class OBJA : IGeneralInfo
{

    public string Info1
    {
        get { return "Info1 is used"; }
    }

    public string Info2
    {
        get { return "Info2 is used"; }
    }
}

class OBJB : IGeneralInfo 
{
    int x;

    public OBJB(int X)
    {
        x = X;
    }

    public string Info1
    {
        get { return "" + x; }
    }

    public string Info2
    {
        get { return ""; /*handle this how you want*/}
    }
}
}

我的所有工作代码(除非复制和粘贴失败)

答案 1 :(得分:0)

拥有公共基类的替代方法是使用一些ItemTemplateSelector。我写了一个通用的:

using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Collections;
using System.Windows.Media;

namespace Utils
{
    /// <summary>
    /// DataType cannot be null -> define Null type
    /// </summary>
    public class Null
    {
    }

    /// <summary>
    /// Generic template selector selecting the template according to the type
    /// </summary>
    [ContentProperty("Items")]
    public class GenericDataTemplateSelector : DataTemplateSelector
    {
        /// <summary>
        /// Select a template according to the type of the object.
        /// </summary>
        /// <param name="item">The item for which a template shall be selected.</param>
        /// <param name="container">The container, in which the Template shall be used.</param>
        /// <returns>The appropriate template, if found; else null.</returns>
        public override DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
        {
            DataTemplate defaultTemplate = null;
            if (item != null)
            {
                foreach (var dataTemplate in Items.OfType<DataTemplate>())
                {
                    if ((Type)dataTemplate.DataType == null || (Type)dataTemplate.DataType == typeof(Null))
                    {
                        defaultTemplate = dataTemplate;
                    }
                    else if (((Type)dataTemplate.DataType).IsInstanceOfType(item))
                    {
                        return dataTemplate;
                    }
                }
            }
            return defaultTemplate;
        }

        /// <summary>
        /// The list of templates.
        /// </summary>
        public IList Items
        {
            get
            {
                if (_items == null)
                {
                    _items = new ArrayList();
                }
                return _items;
            }
            set
            {
                Items.Clear();
                foreach (var item in value)
                {
                    if (item is DataTemplate)
                    {
                        _items.Add(item);
                    }
                }
            }
        }
        IList _items;
    }
}

用法:

    <utils:GenericDataTemplateSelector x:Key="TreeViewTemplateSelector">
        <HierarchicalDataTemplate DataType="{x:Type Type1}">
             ...
        </HierarchicalDataTemplate>

        <HierarchicalDataTemplate DataType="{x:Type Type2}">
             ...
        </HierarchicalDataTemplate>

        <DataTemplate DataType="{x:Type utils:Null}">
             ...
        </DataTemplate>

    </utils:GenericDataTemplateSelector>