WPF datagrid - 当可编辑单元格被“打开”或编辑时,按数据网格分组,可编辑列重新排列组中的行

时间:2011-11-03 05:43:19

标签: wpf .net-3.5 datagrid grouping

分组后,我在WPF数据网格中遇到一个奇怪的问题。组内的行开始重新排序。我正在使用.code 3.5框架的codeplex中的datagrid。

问题已在msdn论坛中提出。请在下面找到链接。

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

msdn用户在帖子的末尾说可能没有解决方法。但我非常需要一个!!

2 个答案:

答案 0 :(得分:2)

您是否尝试过通过CustomSort进行排序?我看到这张贴在某处,它对我有用。它需要一点点发现,但它可以通过ListCollectionView类获得。如下所示:

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

lcv.CustomSort = new YourObjectComparer();

其中YourObjectComparer实现IComparer并对您想要的属性进行排序。

答案 1 :(得分:1)

修改

为此,在进行单元格编辑时,我们会删除组并再次添加它们。这会使细胞保持其预期的顺序。但这带来了另一个问题,即所有扩展器都崩溃了。因此,如果我们记住在重新组合后哪个扩展器仍然扩展,我们就能实现您的目标。


有一些事件可以帮助您实现此功能...

  1. DataGrid.CellEditEnding活动
  2. Expander.InitializedExpander.ExpandedExpander.Collpased次事件
  3. ICollectionView.CurrentChanging活动
  4. 您需要记住的是展开器展开或折叠时的状态。每个展开器代表由Name属性表示的分组值。这些分组值是唯一的。因此,Dictionary.KeyName值且Dictionary.ValueExpander.IsExpanded标志的字典就足够了。

    使用此原材料以下代码可以满足您的需求......

    模型类: 我在DataGrid中表示一个简单的Key-Value对象列表。

    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进行gropup,则假设有员工列表,则会有嵌套扩展器。现在,一些名字分组可能与某些姓氏分组匹配,例如George。因此,字典将落入一个技巧,将无法正常工作。
    3. 希望这有帮助。