2013-07-31 3 views
0

У меня есть TreeView, что я хочу добавить два разных типа узлов, каждый из которых имеет свой собственный HierachicalDataTemplate. У меня есть эта работа (Code Below)Изменение HeaderTemplate в древовидной структуре на IsSelected с несколькими иерархическими параметрами для разных типов

Что я хочу, когда выбран какой-либо узел в дереве, я хочу, чтобы шаблон изменялся для этого узла, с другим шаблоном для узлов BoolNode и другим шаблоном для CompareNodes , Я нашел несколько примеров, используя Styles и Trigger s, но они все для TreeView, где все узлы имеют один и тот же шаблон.

TreeView Xaml:

<TreeView Name="m_kTest"> 
     <TreeView.Resources> 
      <HierarchicalDataTemplate DataType="{x:Type self:BoolNode}" ItemsSource="{Binding Children}"> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="{Binding OpText}"/> 
       </StackPanel> 
      </HierarchicalDataTemplate> 
      <HierarchicalDataTemplate DataType="{x:Type self:CompareNode}"> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="{Binding Header}"/> 
        <TextBlock Text=" "/> 
        <TextBlock Text="{Binding OpText}"/> 
        <TextBlock Text=" "/> 
        <TextBlock Text="{Binding Value}"/> 
       </StackPanel> 
      </HierarchicalDataTemplate> 
     </TreeView.Resources> 
    </TreeView> 

IQueryNode:

public interface IQueryNode 
{ 
    ObservableCollection<IQueryNode> Children { get; } 
    int OpIndex { get; set; } 
    String OpText{get;} 
} 

BoolNode:

public class BoolNode :IQueryNode 
{ 
    public int OpIndex { get; set; } 
    public String OpText { get { ... } } 
    public ObservableCollection<IQueryNode> Children { get; private set; } 

    public BoolNode() 
    { 
     Children = new ObservableCollection<IQueryNode>(); 
    } 
} 

CompareNode:

public class CompareNode: IQueryNode 
{ 
    public ObservableCollection<IQueryNode> Children { get; private set; } 
    public int OpIndex { get; set; } 
    public String OpText {get {...} } 
    public String Header { get; set; } 
    public String Value { get; set; } 

    public CompareNode() 
    { 
     Children = new ObservableCollection<IQueryNode>(); 
    } 
} 
+0

Почему вы не используете 'ObservableCollection ' и не помещаете в него объекты' BoolNode' и 'CompareNode'? –

+0

Это то, что я делаю для построения набора данных. Всегда будет один корневой узел, а затем любое число узлов-предков. У меня есть основной дисплей элементов, работающих с их различными HierarchicalDataTemplates, применяемыми к каждому типу узла. Это изменение шаблона на IsSelected, которое меня озадачило. – user1958698

ответ

1

Я получил эту работу в своем роде " хаки ".

Я добавил свойство IsSelected к моим двум классам и привязал его к свойству IsSelected TreeViewNode. Тогда, так как у меня было только два типа данных я работал, я добавил «IsBoolean» логическое поле и вызвало изменение шаблона на этих двух значений:

TreeView Xaml:

<TreeView Name="m_kTest"> 
     <TreeView.Resources> 
      <HierarchicalDataTemplate x:Key="BoolDisplayTemplate" DataType="{x:Type self:BoolNode}" ItemsSource="{Binding Children}"> /*template*/ </HierarchicalDataTemplate> 
      <HierarchicalDataTemplate x:Key="BoolEditTemplate" DataType="{x:Type self:BoolNode}" ItemsSource="{Binding Children}"> /*template*/ </HierarchicalDataTemplate> 
      <HierarchicalDataTemplate x:Key="CompareEditTemplate" DataType="{x:Type self:CompareNode}" ItemsSource="{Binding Children}"> /*template*/ </HierarchicalDataTemplate> 
      <HierarchicalDataTemplate x:Key="CompareDisplayTemplate" DataType="{x:Type self:CompareNode}" ItemsSource="{Binding Children}"> /*template*/ </HierarchicalDataTemplate> 

     <Style TargetType="{x:Type TreeViewItem}"> 
      <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" /> 
      <Style.Triggers> 
       <MultiDataTrigger> 
        <MultiDataTrigger.Conditions> 
         <Condition Binding="{Binding Path=IsBoolNode}" Value="True"/> 
         <Condition Binding="{Binding Path=IsSelected}" Value="False"/> 
        </MultiDataTrigger.Conditions> 
        <MultiDataTrigger.Setters> 
         <Setter Value="{StaticResource BoolDisplayTemplate}" Property="HeaderTemplate"/> 
        </MultiDataTrigger.Setters> 
       </MultiDataTrigger> 

       <MultiDataTrigger> 
        <MultiDataTrigger.Conditions> 
         <Condition Binding="{Binding Path=IsBoolNode}" Value="True"/> 
         <Condition Binding="{Binding Path=IsSelected}" Value="True"/> 
        </MultiDataTrigger.Conditions> 
        <MultiDataTrigger.Setters> 
         <Setter Value="{StaticResource BoolEditTemplate}" Property="HeaderTemplate"/> 
        </MultiDataTrigger.Setters> 
       </MultiDataTrigger> 

       <MultiDataTrigger> 
        <MultiDataTrigger.Conditions> 
         <Condition Binding="{Binding Path=IsBoolNode}" Value="False"/> 
         <Condition Binding="{Binding Path=IsSelected}" Value="False"/> 
        </MultiDataTrigger.Conditions> 
        <MultiDataTrigger.Setters> 
         <Setter Value="{StaticResource CompareDisplayTemplate}" Property="HeaderTemplate"/> 
        </MultiDataTrigger.Setters> 
       </MultiDataTrigger> 

       <MultiDataTrigger> 
        <MultiDataTrigger.Conditions> 
         <Condition Binding="{Binding Path=IsBoolNode}" Value="False"/> 
         <Condition Binding="{Binding Path=IsSelected}" Value="True"/> 
        </MultiDataTrigger.Conditions> 
        <MultiDataTrigger.Setters> 
         <Setter Value="{StaticResource CompareEditTemplate}" Property="HeaderTemplate"/> 
        </MultiDataTrigger.Setters> 
       </MultiDataTrigger> 
      </Style.Triggers> 
     </Style> 
     </TreeView.Resources> 
    </TreeView> 

IQueryNode:

public interface IQueryNode 
{ 
    ObservableCollection<IQueryNode> Children { get; } 

    int OpIndex { get; set; } 

    String OpText{get;} 
    bool IsBoolNode { get; } 
    bool IsSelected { get; set; } 
} 

BoolNode:

public class BoolNode :IQueryNode 
{ 
    public int OpIndex { get; set; } 
    public String OpText { get { ... } } 
    public ObservableCollection<IQueryNode> Children { get; private set; } 
    public bool IsBoolNode{get{return true;}} 
    public bool IsSelected { get; set;} 

    public BoolNode() 
    { 
     OpIndex = 0; 
     Children = new ObservableCollection<IQueryNode>(); 
     IsSelected = false; 
    } 
} 

CompareNode:

public class CompareNode: IQueryNode 
{ 
    public ObservableCollection<IQueryNode> Children { get; private set; } 
    public int OpIndex { get; set; } 
    public String OpText{ get{ ... } } 
    public String Header { get; set; } 
    public String Value { get; set; } 
    public bool IsBoolNode { get { return false; } } 
    public bool IsSelected { get; set; } 
    public CompareNode() 
    { 
     Children = new ObservableCollection<IQueryNode>(); 
     IsSelected = false; 
    } 
} 
1

Вот так я должен работать, чтобы получить свой стиль только на выбранных элементах

XML:

<Window x:Name="window" 
    x:Class="stackoverflowTreeview.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:t="clr-namespace:System;assembly=mscorlib" 
    xmlns:this="clr-namespace:stackoverflowTreeview" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <this:testConv x:Key="testConv"/> 

    <Style TargetType="TreeView"> 
     <Setter Property="ItemTemplate"> 
      <Setter.Value> 
       <HierarchicalDataTemplate ItemsSource="{Binding Children}"> 
        <ContentControl> 
         <ContentControl.Style> 
          <Style> 
           <Setter Property="ContentControl.Content"> 
            <Setter.Value> 
             <!-- This is the default, common template --> 
             <TextBlock Text="{Binding Name, Converter={StaticResource testConv}}"/> 
            </Setter.Value> 
           </Setter> 
           <Style.Triggers> 
            <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=TreeViewItem}}" Value="True"> 
             <Setter Property="ContentControl.Content"> 
              <Setter.Value> 
               <ContentControl Content="{Binding}"> 
                <ContentControl.Resources> 
                 <!-- These templates are type specific, change them for your desired types --> 
                 <DataTemplate DataType="{x:Type this:Herp}"> 
                  <TextBlock Text="{Binding Name}"/> 
                 </DataTemplate> 
                 <DataTemplate DataType="{x:Type this:Derp}"> 
                  <StackPanel> 
                   <TextBlock Text="{Binding Name}"/> 
                   <TextBlock Text="{Binding Value}"/> 
                  </StackPanel> 
                 </DataTemplate> 
                </ContentControl.Resources> 
               </ContentControl> 
              </Setter.Value> 
             </Setter> 
            </DataTrigger> 
           </Style.Triggers> 
          </Style> 
         </ContentControl.Style> 
        </ContentControl> 
       </HierarchicalDataTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

</Window.Resources> 
    <Grid> 
     <TreeView Name="m_kTest" ItemsSource="{Binding Data, ElementName=window}"> 

     </TreeView> 
    </Grid> 
</Window> 

C#:

using System; 
using System.Collections.Generic; 
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; 

using System.Collections; 

namespace stackoverflowTreeview 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      Data = new List<IHerp>() 
      { 
       new Derp("Derp Root", "Derp Root Value") 
       { 
        Children = new List<IHerp>() 
        { 
         new Herp("Herp Child") 
         { 
          Children = new List<IHerp>() {new Derp("Derp Grandchild","Derp GrandChild Value")} 
         }, 
         new Derp("Derp Child2", "Derp Child2 Value") 
         { 
          Children = new List<IHerp>() {new Derp("Derp Grandchild","Derp GrandChild Value")} 
         }, 
         new Herp("Herp Child") 
         { 
          Children = new List<IHerp>() {new Derp("Derp Grandchild","Derp GrandChild Value")} 
         } 
        } 
       } 
      }; 

     } 

     public static DependencyProperty dData = DependencyProperty.Register("Data", typeof(List<IHerp>), typeof(MainWindow)); 

     public List<IHerp> Data 
     { 
      get { return (List<IHerp>)GetValue(dData); } 
      set { SetValue(dData, value); } 
     } 
    } 

    public abstract class IHerp : DependencyObject 
    { 
     public static DependencyProperty dChildren = DependencyProperty.Register("Children", typeof(List<IHerp>), typeof(IHerp)); 
     public List<IHerp> Children { get { return (List<IHerp>)GetValue(dChildren); } set { SetValue(dChildren, value); } } 
     public static DependencyProperty dName = DependencyProperty.Register("Name", typeof(string), typeof(IHerp)); 
     public string Name { get{return (string)GetValue(dName);} set{SetValue(dName,value);} } 
     public IHerp() 
     { 
      Children = Children == null ? new List<IHerp>() : Children; 
      Name = Name == null ? "" : Name; 
     } 
    } 

    public class Herp : IHerp 
    { 
     public Herp(string name) 
     { 
      Name = name; 
     } 
    } 

    public class Derp : IHerp 
    { 
     public string Value { get; set; } 
     public Derp(string name, string value) 
     { 
      Name = name; 
      Value = value; 
     } 
    } 
    public class testConv : IValueConverter 
    { 

     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      try 
      { 
       return value; 
      } 
      catch { return typeof(object); } 
     } 

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

У меня есть шаблоны, привязанные к типу, его конструкция и расположение триггера (ов), который отключает меня. А именно, как мне создать отдельные триггеры для разных типов и шаблонов с привязкой к типу? – user1958698

+0

Это работает для плоского дерева, но как только я добавляю ItemSource в HierarchicalDataTemplates и дочерние элементы к корневому узлу, ни один из дочерних элементов не нарисован для начала (т. Е. Только дерево корня появляется в дереве) – user1958698

+0

Я думаю, что я 'довольно близко к решению с этим новым правлением – Anthony