【问题标题】:WPF datagrid - Group by datagrid with editable column reoders rows in group when editable cell is "opened" or editedWPF datagrid - 当可编辑单元格“打开”或编辑时,按数据网格分组,可编辑列重新编排组中的行
【发布时间】:2011-12-20 21:38:20
【问题描述】:

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

这个问题已经在msdn论坛上问过了。请在下面找到链接。

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

msdn 用户在线程结束时说可能没有解决方法。但我非常需要一个!!

【问题讨论】:

  • 您可以将 DataGrid ItemsSource 绑定到 CollectionViewSource 并使用 SortDescription 指定您的排序顺序,这样项目就不会被重新排序。
  • @bjoshi - 我也在做同样的事情,但它正在重新排序!

标签: wpf .net-3.5 datagrid grouping


【解决方案1】:

您是否尝试过通过 CustomSort 进行排序?我在某个地方看到了这个帖子,它对我有用。花了一点时间寻找,但可以通过 ListCollectionView 类获得。所以像:

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

lcv.CustomSort = new YourObjectComparer();

YourObjectComparer 在哪里实现 IComparer 并对您想要的属性进行排序。

【讨论】:

    【解决方案2】:

    编辑:

    为此,当进行单元格编辑时,我们会删除组并再次添加它们。这使单元格保持在其预期的顺序上。但这带来了另一个问题,即所有扩展器都已折叠。因此,如果我们记得重组后哪些扩展器仍然处于扩展状态,我们就能实现您所寻求的。


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

    1. DataGrid.CellEditEnding事件
    2. Expander.Initialized、Expander.Expanded 和 Expander.Collpased 事件
    3. ICollectionView.CurrentChanging事件

    您只需要记住展开器在展开或折叠时的状态。每个扩展器代表由Name 属性表示的分组值。这些分组值是唯一的。因此,Dictionary.Key 是 Name 值和 Dictionary.Value 是 Expander.IsExpanded 标志的字典就足够了。

    有了这个原材料,下面的代码就可以满足你的需求......

    模型类: 我在 DataGrid 中表示一个简单的键值对象列表。

    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。所以字典会落入陷阱,无法正常工作。

    希望这会有所帮助。

    【讨论】:

    • 我的问题和你的回答似乎并不符合我的想法。我不是在问如何分组或如何保持扩展。我的问题是如何防止重新排序。 !
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-13
    • 2012-12-04
    • 1970-01-01
    • 2011-11-27
    相关资源
    最近更新 更多