我想将两个或更多类数据绑定为 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属性为彼此。现在我们需要为创建节点绑定两种类型。一个用于文件,一个用于文件夹。我们怎么做到这一点?
答案 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>