2010-08-11 25 views
19

मैं एक WPF नियंत्रण जो TreeView और डेटा ग्रिड, विजुअल स्टूडियो डीबगर या QuickBooks संपर्क सूची आदिWPF: संभाल संपादन योग्य श्रेणीबद्ध डेटा/TreeView ~ डेटा ग्रिड संकर

पर कोई अन्य समाधान की तरह कुछ के एक संकर है रहा हूँ डब्ल्यूपीएफ में संपादन योग्य पदानुक्रमित डेटा को कैसे संभालना है, इसका भी बहुत स्वागत किया जाएगा।

enter image description here

उत्तर

3

सिर्फ यह अगर आप अपने दृश्य मॉडल ठीक से डिजाइन को लागू करने के एक यथोचित सीधा बात की तरह मुझे लगता है इस पर नियंत्रण

http://www.codeproject.com/KB/WPF/wpf_treelistview_control.aspx

+0

लेकिन मैं इसे डेटाग्रिड (संपादन योग्य) – Shimmy

+1

+1 @Shimmy कॉम के साथ हाइब्रिड करना चाहता हूं http://www.codeproject.com/KB/WPF/wpf_treelistview_control.aspx का ments हिस्सा। यह दिखाता है कि इसे सूचीदृश्य – k3b

+0

@ k3b के बजाय ग्रिड के साथ कैसे उपयोग किया जाए, आपको यह @ हेज निर्देशित करना चाहिए था। मुझे लगता है कि यह वास्तव में एक समस्या नहीं है @Shimmy अब और परवाह करता है ... बस कह रहा है ... –

7

पर एक नजर है।

आप मूल रूप से आइटम को उसी तरह डिज़ाइन करते हैं जैसे आप उन्हें सामान्य डेटा ग्रिड में प्रदर्शित करते हैं, यानी प्रत्येक आइटम में प्रत्येक कॉलम के लिए एक संपत्ति होती है। सभी संभावनाओं में, आपका अंतर्निहित डेटा मॉडल पदानुक्रमित है, लेकिन ग्रिड को संग्रहित करने वाला संग्रह फ़्लैटन होने जा रहा है, यानी माता-पिता/बाल संबंधों के बावजूद पदानुक्रम में प्रत्येक नोड के लिए एक आइटम शामिल होगा। Level, Children, IsExpanded, और IsVisible:

आइटम दृश्य मॉडल कुछ अतिरिक्त गुण है। Level नोड के पूर्वजों की गिनती है, Children में बच्चे दृश्य मॉडल नोड्स, IsExpanded यूआई में उपयोग किया जाता है, और IsVisible सही है यदि नोड दिखाई दे रहा है।

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

आप नियंत्रण के पहले कॉलम में आइटम के लिए शैली में Level, HasChildren, और IsExpanded का उपयोग करें:: यह भी एक संपत्ति VisibleDescendants कहा जाता है को लागू करता है वे बाईं मार्जिन और आइकन की किस तरह (अगर कोई है) पर नियंत्रण है का प्रदर्शन किया।

आपको ExpandCommand और CollapseCommand गुणों को लागू करने की भी आवश्यकता है। ExpandCommand सक्षम है यदि Children.Any() सत्य है और IsExpanded गलत है, और CollapseCommand सक्षम है यदि Children.Any() सत्य है और IsExpanded सत्य है। इन आदेशों को निष्पादित करते समय, IsExpanded का मान बदलें।

और यहां पर यह दिलचस्प हो जाता है। इसे लागू करने का सरल तरीका आपके लिए काम कर सकता है: आइटम को मूल दृश्य मॉडल द्वारा उजागर किया जाता है जिसका Items संपत्ति संग्रह नहीं है। इसके बजाय, यह एक प्रगणक है कि बच्चे को देखने के मॉडल की श्रृंखला के नीचे यात्रा करता है और ही दिखाई नोड्स पैदावार है:

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

जब भी कोई वंशज के IsVisible गुण परिवर्तन, जनक दृश्य मॉडल Items संपत्ति है, जो डेटा बलों के लिए PropertyChanged को जन्म देती है ग्रिड repopulate करने के लिए।

वहाँ एक कम सरल कार्यान्वयन भी जहां Items संपत्ति एक वर्ग है कि INotifyCollectionChanged लागू करता बना देते हैं, और जब वंशज नोड्स दिखाई/अदृश्य हो कि उचित CollectionChanged घटनाओं को जन्म देती है, लेकिन आप केवल वहाँ जाने के लिए करता है, तो प्रदर्शन एक मुद्दा है चाहता हूँ ।

+0

यह बेहद काम करता है !! – faztp12

0

मैं पाया है कि सबसे अच्छा MVVM दृष्टिकोण इस पर नियंत्रण के साथ संभव है: http://blogs.msdn.com/b/atc_avalon_team/archive/2006/03/01/541206.aspx

पदानुक्रमिक दृश्य मॉडल के साथ इसका इस्तेमाल करने के लिए, आप यहाँ से श्रेणीबद्ध डेटा टेम्पलेट और देखने मॉडल मार्गदर्शिका का उपयोग कर सकते हैं: http://www.codeproject.com/Articles/24973/TreeListView

2

के बाद जवाब @Robert Rossney के जवाब से विकसित की है:

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); 
     } 
    } 
} 

ऊपर वर्ग वह क्या समझाया है। Data ऑब्जेक्ट का उपयोग DataGridHierarchialDataModel में अपने स्वयं के कस्टम डेटा में रखने के लिए करें, और अपने पदानुक्रमित डेटा को उत्पन्न करें और इसे DataGridHierarchialData s RawData पर रखें। Initialize पर कॉल करें जब हर चीज किया जाता है;

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; 

^यह मेरा परिदृश्य, समूह के लिए लेखा

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> 

यही बिग: पी लेकिन मुझ पर भरोसा, रॉबर्ट Rossney के विचार एक विस्फोट इसके अलावा, है :) विस्तारक ' + ',' - 'शैलियों को भी शामिल किया गया है (टिप्पणी की गई) उम्मीद है कि यह मदद करता है :)

संबंधित मुद्दे