2010-08-11 7 views

Antwort

3
+0

Aber ich möchte es mit einem DataGrid (editierbar) – Shimmy

+1

+1 @Shimmy See com Hybrid Teil von http://www.codeproject.com/KB/WPF/wpf_treelistview_control.aspx. es zeigt, wie man es mit einem Raster statt einer Listenansicht verwendet – k3b

+0

@ k3b sollten Sie diese @Hedge gerichtet haben. Ich denke, das ist nicht wirklich ein Problem @ Shimmy kümmert sich nicht mehr um ... nur zu sagen ... –

7

dies wie eine ziemlich einfache Sache, mir scheint, zu implementieren, wenn Sie richtig Ihre Ansicht Modell entwerfen.

Sie entwerfen die Elemente grundsätzlich so, als würden Sie sie in einem normalen Datenraster anzeigen, d. H. Jedes Element verfügt über eine Eigenschaft für jede Spalte. Das zugrundeliegende Datenmodell ist aller Wahrscheinlichkeit nach hierarchisch, aber die Sammlung, an die das Raster gebunden ist, wird abgeflacht, d. H. Es enthält ein Element für jeden Knoten in der Hierarchie, unabhängig von Eltern/Kind-Beziehungen.

Der Artikel View-Modell hat einige zusätzliche Eigenschaften: Level, Children, IsExpanded und IsVisible. Level ist eine Anzahl der Vorfahren des Knotens, Children enthält die untergeordneten Ansichtsmodellknoten, IsExpanded wird in der Benutzeroberfläche verwendet, und IsVisible ist wahr, wenn der Knoten sichtbar ist. Es implementiert eine Eigenschaft namens VisibleDescendants:

public IEnumerable<NodeViewModel> VisibleDescendants 
{ 
    get 
    { 
     return Children 
      .Where(x => x.IsVisible) 
      .SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants))); 
    } 
} 

Sie Level verwenden, HasChildren und IsExpanded im Stil für das Element in der ersten Spalte der Kontrolle: Sie steuern den linken Rand und welche Art von Symbol (falls vorhanden) ist angezeigt.

Sie müssen auch die Eigenschaften ExpandCommand und CollapseCommand implementieren. Die ExpandCommand ist aktiviert, wenn Children.Any() ist wahr und IsExpanded ist falsch, und die CollapseCommand ist aktiviert, wenn Children.Any() ist wahr und IsExpanded ist wahr. Diese Befehle ändern bei ihrer Ausführung den Wert IsExpanded.

Und hier wird es interessant. Die einfache Möglichkeit, dies zu implementieren, funktioniert möglicherweise für Sie: Die Elemente werden von einem übergeordneten Ansichtsmodell bereitgestellt, dessen Items-Eigenschaft keine Sammlung ist. Stattdessen ist es ein Enumerator, die Kette der untergeordneten Ansicht Modelle reist nach unten und liefert nur den sichtbaren Knoten:

public IEnumerable<NodeViewModel> Items 
{ 
    get 
    { 
     return _Items 
      .Where(x => x.IsVisible) 
      .SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants)); 
    } 
} 

Wann immer einen IsVisible Eigenschaftsänderungen des Nachkommen, das übergeordnete Ansicht Modell wirft PropertyChanged für die Items Eigenschaft, die die Daten zwingt Raster neu zu bevölkern.

Es gibt eine weniger einfache Implementierung zu, wo Sie die Items Eigenschaft eine Klasse machen, die INotifyCollectionChanged implementiert, und das wirft die richtigen CollectionChanged Ereignisse, wenn absteigende Knoten sichtbar/unsichtbar, aber Sie wollen nur dorthin gehen, wenn die Leistung ist ein Problem .

+0

Das funktioniert super !! – faztp12

2

folgende Antwort von @ Robert Rossney Antwort entwickelt:

public class DataGridHierarchialDataModel 
{ 

    public DataGridHierarchialDataModel() { Children = new List<DataGridHierarchialDataModel>(); } 


    public DataGridHierarchialDataModel Parent { get; set; } 
    public DataGridHierarchialData DataManager { get; set; } 
    public void AddChild(DataGridHierarchialDataModel t) 
    { 
     t.Parent = this; 
     Children.Add(t); 
    } 


    #region LEVEL 
    private int _level = -1; 
    public int Level 
    { 
     get 
     { 
      if (_level == -1) 
      {      
       _level = (Parent != null) ? Parent.Level + 1 : 0; 
      } 
      return _level; 
     } 
    } 

    #endregion 
    public bool IsExpanded 
    { 
     get { return _expanded; } 
     set 
     { 
      if (_expanded != value) 
      { 
       _expanded = value; 
       if (_expanded == true) 
        Expand(); 
       else 
        Collapse(); 
      } 
     } 
    } 


    public bool IsVisible 
    { 
     get { return _visible; } 
     set 
     { 
      if (_visible != value) 
      { 
       _visible = value; 
       if (_visible) 
        ShowChildren(); 
       else 
        HideChildren(); 
      } 
     } 
    } 
    public bool HasChildren { get { return Children.Count > 0; } } 
    public List<DataGridHierarchialDataModel> Children { get; set; } 



    public object Data { get; set; } // the Data (Specify Binding as such {Binding Data.Field}) 

    public IEnumerable<DataGridHierarchialDataModel> VisibleDescendants 
    { 
     get 
     {    
      return Children 
       .Where(x => x.IsVisible) 
       .SelectMany(x => (new[] {x}).Concat(x.VisibleDescendants));    
     } 
    } 



    // Expand Collapse 
    private bool _expanded = false; 
    private bool _visible = false; 
    private void Collapse() 
    { 
     DataManager.RemoveChildren(this); 
     foreach (DataGridHierarchialDataModel d in Children) 
      d.IsVisible = false; 
    } 

    private void Expand() 
    { 
     DataManager.AddChildren(this); 
     foreach (DataGridHierarchialDataModel d in Children) 
      d.IsVisible = true; 
    } 




    // Only if this is Expanded 
    private void HideChildren() 
    { 
     if (IsExpanded) 
     { 
      // Following Order is Critical 
      DataManager.RemoveChildren(this); 
      foreach (DataGridHierarchialDataModel d in Children) 
       d.IsVisible = false; 
     } 
    } 
    private void ShowChildren() 
    { 
     if (IsExpanded) 
     { 
      // Following Order is Critical 
      DataManager.AddChildren(this); 
      foreach (DataGridHierarchialDataModel d in Children) 
       d.IsVisible = true; 
     } 
    } 
} 

public class DataGridHierarchialData : ObservableCollection<DataGridHierarchialDataModel> 
{ 

    public List<DataGridHierarchialDataModel> RawData { get; set; } 
    public DataGridHierarchialData() { RawData = new List<DataGridHierarchialDataModel>(); } 

    public void Initialize() 
    { 
     this.Clear(); 
     foreach (DataGridHierarchialDataModel m in RawData.Where(c => c.IsVisible).SelectMany(x => new[] { x }.Concat(x.VisibleDescendants))) 
     {     
      this.Add(m); 
     } 
    } 

    public void AddChildren(DataGridHierarchialDataModel d) 
    { 
     if (!this.Contains(d)) 
      return; 
     int parentIndex = this.IndexOf(d); 
     foreach (DataGridHierarchialDataModel c in d.Children) 
     { 
      parentIndex += 1; 
      this.Insert(parentIndex, c); 
     } 
    } 

    public void RemoveChildren(DataGridHierarchialDataModel d) 
    { 
     foreach (DataGridHierarchialDataModel c in d.Children) 
     { 
      if (this.Contains(c)) 
       this.Remove(c); 
     } 
    } 
} 

Die obige Klasse ist, was er erklärt. Verwenden Sie das Objekt Data in der DataGridHierarchialDataModel, um Ihre eigenen benutzerdefinierten Daten zu platzieren, und generieren Sie Ihre hierarchischen Daten und platzieren Sie sie in DataGridHierarchialData s RawData. Rufen Sie Initialize wenn alles erledigt ist;

DataTable accTable = await DB.getDataTable("SELECT * FROM Fm3('l1')"); 
     accTable.DefaultView.Sort = "iParent"; 

     DataGridHierarchialData data = new DataGridHierarchialData(); 

     Action<DataRowView, DataGridHierarchialDataModel> Sort = null; 
     Sort = new Action<DataRowView, DataGridHierarchialDataModel>((row, parent) => 
     { 
      DataGridHierarchialDataModel t = new DataGridHierarchialDataModel() { Data = row, DataManager = data }; 
      if (row["iGroup"].ToString() == "1") 
      {      
       foreach (DataRowView r in accTable.DefaultView.FindRows(row["iSmajId"])) 
        Sort(r, t); 
      } 
      parent.AddChild(t); 
     }); 

     foreach (DataRowView r in accTable.DefaultView.FindRows(0)) 
     { 
      DataGridHierarchialDataModel t = new DataGridHierarchialDataModel() { Data = r, DataManager = data }; 
      if (r["iGroup"].ToString() == "1") 
      {      
       foreach (DataRowView rf in accTable.DefaultView.FindRows(r["iSmajId"])) 
        Sort(rf, t); 
      } 

      t.IsVisible = true; // first layer 
      data.RawData.Add(t); 
     } 
     data.Initialize(); 
     dg.ItemsSource = data; 

^Das war mein Szenario Gruppenkonten

XAML:

<DataGrid x:Name="dg" AutoGenerateColumns="False" IsReadOnly="False" CanUserAddRows="False" GridLinesVisibility="All" ColumnWidth="*"> 

     <DataGrid.Columns> 
      <DataGridTextColumn Header="Name" Binding="{Binding Data.sName}"> 
       <DataGridTextColumn.CellStyle> 
        <Style TargetType="DataGridCell" BasedOn="{StaticResource MetroDataGridCell}"> 
         <Setter Property="Template"> 
          <Setter.Value> 

           <ControlTemplate TargetType="DataGridCell"> 
            <Border BorderBrush="{TemplateBinding BorderBrush}" 
             BorderThickness="{TemplateBinding BorderThickness}" 
             Background="{TemplateBinding Background}" 
             SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"> 

             <StackPanel Orientation="Horizontal"> 
              <ToggleButton x:Name="Expander"            
              Margin="{Binding Level,Converter={StaticResource LevelToIndentConverter}}" 
              IsChecked="{Binding Path=IsExpanded, UpdateSourceTrigger=PropertyChanged}" 
              ClickMode="Press" > 
               <ToggleButton.Style> 
                <Style TargetType="{x:Type ToggleButton}"> 
                 <Setter Property="Focusable" Value="False"/> 
                 <Setter Property="Width" Value="19"/> 
                 <Setter Property="Height" Value="13"/> 
                 <Setter Property="Template"> 
                  <Setter.Value> 
                   <ControlTemplate TargetType="{x:Type ToggleButton}"> 
                    <Border Width="19" Height="13" Background="Transparent"> 
                     <Border Width="9" Height="9" 
                       BorderThickness="0" 
                       BorderBrush="#FF7898B5" 
                       CornerRadius="1" 
                       SnapsToDevicePixels="true"> 
                      <Border.Background> 
                       <SolidColorBrush Color="Transparent"/> 
                       <!-- 
                        <LinearGradientBrush StartPoint="0,0" 
                         EndPoint="1,1"> 
                         <LinearGradientBrush.GradientStops> 
                          <GradientStop Color="White" 
                        Offset=".2"/> 
                          <GradientStop Color="#FFC0B7A6" 
                        Offset="1"/> 
                         </LinearGradientBrush.GradientStops> 
                        </LinearGradientBrush> 
                       --> 
                      </Border.Background> 
                      <Path x:Name="ExpandPath"          
                      Data="M0,0 L0,6 L6,0 z" 
                      Fill="Transparent" 
                      Stroke="{DynamicResource BlackBrush}" Margin="1,2,1,1"> 
                       <Path.RenderTransform> 
                        <RotateTransform Angle="135" 
                        CenterY="3" 
                        CenterX="3" /> 
                       </Path.RenderTransform> 
                      </Path> 
                      <!-- 
                      <Path x:Name="ExpandPath" 
                      Margin="1,1,1,1" 
                      Fill="Black" 
                      Data="M 0 2 L 0 3 L 2 3 L 2 5 L 3 5 L 3 3 L 5 3 L 5 2 L 3 2 L 3 0 L 2 0 L 2 2 Z"/> 
                      --> 
                     </Border> 
                    </Border> 
                    <ControlTemplate.Triggers> 
                     <Trigger Property="IsChecked" 
                      Value="True"> 
                      <Setter Property="RenderTransform" 
                       TargetName="ExpandPath"> 
                       <Setter.Value> 
                        <RotateTransform Angle="180" 
                        CenterY="3" 
                        CenterX="3" /> 
                       </Setter.Value> 
                      </Setter> 
                      <Setter Property="Fill" 
                       TargetName="ExpandPath" 
                       Value="{DynamicResource GrayBrush1}" /> 
                      <Setter Property="Stroke" 
                       TargetName="ExpandPath" 
                       Value="{DynamicResource BlackBrush}" /> 

                       <!-- 
                        <Setter Property="Data" 
                      TargetName="ExpandPath" 
                      Value="M 0 2 L 0 3 L 5 3 L 5 2 Z"/> 
                      --> 
                     </Trigger> 
                    </ControlTemplate.Triggers> 
                   </ControlTemplate> 
                  </Setter.Value> 
                 </Setter> 
                </Style> 
               </ToggleButton.Style> 
              </ToggleButton> 

              <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" 
                 Content="{TemplateBinding Content}" 
                 ContentStringFormat="{TemplateBinding ContentStringFormat}" 
                 Margin="{TemplateBinding Padding}" 
                 SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                 VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                 HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" /> 


             </StackPanel> 
            </Border> 
            <ControlTemplate.Triggers> 
             <DataTrigger Binding="{Binding HasChildren}" Value="False"> 
              <Setter TargetName="Expander" Property="Visibility" Value="Hidden"/> 
             </DataTrigger> 
            </ControlTemplate.Triggers> 
           </ControlTemplate> 
          </Setter.Value> 
         </Setter> 
        </Style> 
       </DataGridTextColumn.CellStyle> 
      </DataGridTextColumn> 
      <DataGridTextColumn Header="Code" Binding="{Binding Data.sCode}"/> 
      <DataGridTextColumn Header="Type" Binding="{Binding Data.c867x1}"/> 

     </DataGrid.Columns> 
    </DataGrid> 

Das ist Big: P aber glauben Sie mir, Idee Robert Rossney das ist eine Explosion :) Auch Expander ' + ',' - 'Styles sind ebenfalls enthalten (auskommentiert) Hoffe es hilft :)