2011-11-03 5 views
1

그룹화 후 WPF DataGrid에서 이상한 문제가 있습니다. 그룹 내부의 행이 재정렬을 시작합니다. 나는 .net 3.5 프레임 워크의 DataGrid를 codeplex에서 사용하고 있습니다.WPF DataGrid - 편집 가능한 열이있는 데이터 격자로 그룹화 편집 가능한 셀을 "열었거나 편집 할 때 그룹의 행을 다시 렌더링합니다.

msdn 포럼에서 문제가 발생했습니다. 아래 링크를 찾으십시오. 은 MSDN 사용자가 가지고있는

http://social.msdn.microsoft.com/Forums/en/wpf/thread/3f915bf9-2571-43e8-8560-3def1d0d65bb

어떤 해결 방법이 없을 수도 스레드의 끝에서 말했다. 그러나 나는 그것을 나쁘게 필요로한다!!

+0

DataGrid ItemsSource를 CollectionViewSource에 바인딩하고 SortDescription을 사용하여 항목의 순서를 바꾸지 않는 정렬 순서를 지정할 수 있습니다. – whoisthis

+0

@bjoshi - 나는 또한 같은 일을하고있다. 그러나 그것은 순서가 바뀌고있다! – GuruC

답변

1

편집 : 셀 편집이 발생하는 경우이를 위해

, 우리는 그룹을 제거하고 다시 추가합니다. 이것은 세포가 예정된 순서대로 머물러 있도록한다. 그러나 이것은 모든 확장기가 붕괴 된 또 다른 문제를 야기합니다. 재편성 후에 확장기가 확장 된 것을 기억한다면, 우리는 당신이 추구하는 것을 성취합니다. 이 기능을 달성하는 당신을 도울 수있는 몇 가지 이벤트가


...

  1. DataGrid.CellEditEnding 이벤트
  2. Expander.Initialized, Expander.ExpandedExpander.Collpased 이벤트
  3. ICollectionView.CurrentChanging 이벤트

당신이 필요로하는 모든 것 확장기가 확장되거나 축소 될 때 확장기의 상태가 기억됩니다. 각 확장자는 Name 속성으로 표시된 그룹화 된 값을 나타냅니다. 이러한 그룹화 된 값은 고유합니다. 따라서 Dictionary.KeyName 값이고 Dictionary.Value 인 사전은 Expander.IsExpanded 플래그로 충분합니다. 나는 데이터 그리드에서 키 - 값 오브젝트의 간단한 목록을 나타냅니다원료 다음 코드와

모델 클래스 ... 당신이 무엇을 추구한다.

public class MyKeyValuePair<TKey, TValue> : INotifyPropertyChanged 
{ 
    private TKey key; 
    private TValue value; 

    public MyKeyValuePair(TKey k, TValue v) 
    { 
     key = k; 
     value = v; 
    } 

    public TKey Key 
    { 
     get { return key; } 
     set { 
      key = value; 
      OnPropertyChanged("Key"); 
     } 
    } 

    public TValue Value 
    { 
     get { return value; } 
     set { 
      this.value = value; 
      OnPropertyChanged("Value"); 
     } 
    } 

    public void OnPropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
     { 
      this.PropertyChanged 
       (this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

XAML : 뒤에

<tk:DataGrid 
    ItemsSource="{Binding}" 
    CellEditEnding="MyDataGrid_CellEditEnding"> 
    <tk:DataGrid.GroupStyle> 
     <GroupStyle> 
      <GroupStyle.HeaderTemplate> 
      <DataTemplate> 
       <StackPanel> 
        <TextBlock Text="{Binding Path=Name}" /> 
       </StackPanel> 
      </DataTemplate> 
      </GroupStyle.HeaderTemplate> 
     <GroupStyle.ContainerStyle> 
     <Style TargetType="{x:Type GroupItem}"> 
      <Setter Property="Template"> 
       <Setter.Value> 
       <ControlTemplate TargetType="{x:Type GroupItem}"> 
        <Expander 
         Initialized="Expander_Initialized" 
         Expanded="Expander_Expanded" 
         Collapsed="Expander_Expanded"> 
         <Expander.Header> 
          <StackPanel Orientation="Horizontal"> 
           <TextBlock 
            Text="{Binding Path=Name}" /> 
           <TextBlock Text=" (" /> 
           <TextBlock 
            Text="{Binding Path=ItemCount}"/> 
           <TextBlock Text="(" /> 
           <TextBlock Text="Items"/> 
          </StackPanel> 
         </Expander.Header> 
         <ItemsPresenter /> 
        </Expander> 
       </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 
    </GroupStyle.ContainerStyle> 
    </GroupStyle> 
</tk:DataGrid.GroupStyle> 
</tk:DataGrid> 

Window.cs 코드 :

public partial class Window8 : Window 
{ 
    private Dictionary<string, bool> _dict; 
    public Window8() 
    { 
     InitializeComponent(); 

     _dict = new Dictionary<string, bool>(); 

     var list1 = new List<MyKeyValuePair<string, int>>(); 
     var random = new Random(); 
     for (int i = 0; i < 50; i++) 
     { 
      list1.Add(new MyKeyValuePair<string, int>(
       i.ToString(), random.Next(300) % 3)); 
     } 

     var colView = new ListCollectionView(list1); 
     colView.GroupDescriptions.Add(
      new PropertyGroupDescription("Value")); 
     this.DataContext = colView; 
    } 

    private void MyDataGrid_CellEditEnding 
     (object sender, DataGridCellEditEndingEventArgs e) 
    { 
     var dg = sender as DataGrid; 
     var cellInfo = dg.CurrentCell; 
     var mySource = dg.ItemsSource as ListCollectionView; 
     var oldDlg 
      = new CurrentChangingEventHandler((obj, args) => { return; }); 
     var dlg = new CurrentChangingEventHandler(
      (obj, args) => 
      { 
       if (cellInfo.Item == mySource.CurrentItem) 
       { 
        var grpDescs = mySource.GroupDescriptions; 
        var oldGrpDescs 
         = grpDescs.Cast<PropertyGroupDescription>().ToList(); 
        mySource.Dispatcher.BeginInvoke(
         new Action(
          () => 
          { 
           grpDescs.Clear(); 

           foreach (var grdpDesc in oldGrpDescs) 
           { 
            grpDescs.Add(grdpDesc); 
           } 

           mySource.CurrentChanging -= oldDlg; 
          })); 
       } 
      }); 

     oldDlg = dlg; 
     mySource.CurrentChanging -= oldDlg; 
     mySource.CurrentChanging += oldDlg; 
    } 

    private void Expander_Expanded(object sender, RoutedEventArgs e) 
    { 
     var exp = sender as Expander; 
     var dc = exp.DataContext as CollectionViewGroup; 
     _dict[dc.Name.ToString()] = exp.IsExpanded; 
    } 

    private void Expander_Initialized(object sender, EventArgs e) 
    { 
     var exp = sender as Expander; 
     var dc = exp.DataContext as CollectionViewGroup; 
     if (_dict != null 
      && _dict.ContainsKey(dc.Name.ToString()) 
      && _dict[dc.Name.ToString()]) 
     { 
      exp.IsExpanded = true; 
     } 
    } 
} 

그러나이 무역 오프가 있습니다.

  1. 이렇게하면 데이터 그리드의 많은 수의 항목에 대해 각 셀 편집 속도가 느려집니다. 재편성은 각 셀 편집 시도 후에 수행되기 때문입니다.
  2. 사전에 Name 키가 고유하게 유지되거나 유지되지 않을 수 있으므로 여러 그룹 설명에 대해 작동하지 않을 수 있습니다. 예 :FirstName에 그룹화하고 LastName로 그룹을 만들면 직원 목록에 대해 중첩 된 확장기가 있다고 가정합니다. 이제 일부 이름 그룹은 George과 같은 성 그룹과 일치 할 수 있습니다. 그래서 사전은 트릭에 빠지며 제대로 작동하지 않습니다.

희망이 도움이됩니다.

+0

내 질문과 대답이 내 생각에 맞지 않는 것 같습니다. 그룹화 방법이나 확장 방법을 묻지 않습니다. 제 질문은 순서 재 지정을 방지하는 방법이었습니다. ! – GuruC

+0

이 코드가 수행하는 작업은 무엇입니까? 이 코드를 테스트 했습니까? –

2

CustomSort를 통해 정렬을 시도 했습니까? 나는 이것이 어딘가에 게시 된 것을 보았고 그것이 나를 위해 일했다. 약간의 발견이 있었지만 ListCollectionView 클래스를 통해 사용할 수 있습니다. 그래서 같은 : YourObjectComparer 당신이 원하는 특성에 IComparer 및 종류를 구현

ListCollectionView lcv = 
    (ListCollectionView)CollectionViewSource.GetDefaultView(YourObjectCollection); 

lcv.CustomSort = new YourObjectComparer(); 

.