WPF DataGrid: автоматическая повторная сортировка столбца DataGridTemplateColumn

В элементе управления WPF DataGrid, если вы установите для столбца один из типов столбцов по умолчанию (например, DataGridTextColumn или DataGridCheckBoxColumn), выполните сортировку по этому столбцу, а затем измените его значение, сетка будет автоматически пересортирована.

Однако, если вы используете DataGridTemplateColumn (и разрешаете сортировку столбца), его можно отсортировать, но изменение значения ячейки в этом столбце не приводит к повторной сортировке сетки. Как я могу заставить его автоматически запускать повторную сортировку?

XAML:

<DataGrid Name="grid" AutoGenerateColumns="False">
  <DataGrid.Columns>
    <DataGridTextColumn Header="First name" Binding="{Binding First}"/>
    <DataGridTemplateColumn Header="Last name" SortMemberPath="Last">
      <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
          <TextBox Text="{Binding Last}"/>
        </DataTemplate>
      </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
  </DataGrid.Columns>
</DataGrid>

Привязка:

ObservableCollection items = new ObservableCollection();
grid.ItemsSource = items;
items.Add(new Character() { First = "Homer", Last = "Simpson" });
items.Add(new Character() { First = "Kent", Last = "Brockman" });
items.Add(new Character() { First = "Montgomery", Last = "Burns" });

Вот мой класс предметов, на всякий случай:

public class Character : INotifyPropertyChanged {
    private string first, last;
    public event PropertyChangedEventHandler PropertyChanged;
    private void Notify(string name) {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
    public string First { get { return first; } set { first = value; Notify("First"); } }
    public string Last { get { return last; } set { last = value; Notify("Last"); } }
}

person Jivlain    schedule 24.10.2010    source источник
comment
Кажется, у меня все работает нормально. Вы имеете в виду, что вы меняете значение SortMemberPath для DataGridTemplateColumn?   -  person Fredrik Hedblad    schedule 25.10.2010
comment
Он сортируется, когда вы явно щелкаете по нему или когда вы меняете значение столбца FirstName, но не выполняет повторную сортировку, когда вы меняете значение столбца LastName. Установка SortMemberPath позволяет ему сортировать, но не выполняет автоматическую повторную сортировку, отсюда и проблема.   -  person Jivlain    schedule 25.10.2010
comment
В этой ситуации я заметил изменения необходимого свойства и вызвал SomeCollectionViewOfGrid.Refresh ();   -  person vortexwolf    schedule 24.01.2011


Ответы (6)


Я тоже ищу ответ на этот вопрос. Я нашел одно решение: (не доволен, но ...)

Когда ваша коллекция будет обновлена, вы можете сделать это:

SortDescription sortDescription = grdData.Items.SortDescriptions[0];
grdData.ItemsSource = null;
grdData.ItemsSource = Data;
grdData.Items.SortDescriptions.Add(sortDescription);

Уродливо, но это работает. Вы захотите сохранить всю коллекцию, в отличие от моего примера, в котором используется только первый элемент.

Одна из проблем с этим заключается в том, что DataGrid теряет заголовок, указывающий на сортировку, поэтому, хотя он правильно обрабатывает, заголовок столбца больше не выбирается стрелкой, показывающей направление сортировки.

person Kelly    schedule 27.06.2011
comment
Нет необходимости в сбросе ItemsSource. В моем приложении SortDescriptions.Clear(); вместо этого работает отлично. - person Diligent Key Presser; 27.04.2016

Я знаю, что это старый, но у меня возникла проблема повторной сортировки DataGridTemplateColumn. Этого не происходит с DataGridTextColumn. Я исправляю это с неизменным направлением сортировки в заголовке столбца:

// after updating the collection, remove all SortDescription and add'em back.
SortDescriptionCollection sortDescriptions = new SortDescriptionCollection();
foreach (SortDescription sd in dataGrid.Items.SortDescriptions)
{
    sortDescriptions.Add(sd);
}
dataGrid.Items.SortDescriptions.Clear();

foreach (SortDescription sd in sortDescriptions)
{
    dataGrid.Items.SortDescriptions.Add(sd);
}

Надеюсь, это поможет людям.

person Peter    schedule 15.01.2014

Ни один из этих ответов в 2016 году у меня не сработал.

После некоторой попытки и ошибки я придумал это, и, похоже, он работает нормально:

dataGrid.Items.IsLiveSorting = true;
person wotanii    schedule 02.11.2016

У меня был DataGrid в C # WPF под VS2010, который не сортируется независимо от настроек XAML. По какой-то причине у этой скрытой DataGrid (на дополнительной вкладке) были проблемы с порядком сортировки, когда основной DataGrid был в порядке с аналогичными настройками. Таким образом, мне пришлось схематически отсортировать DataGrid. Вот мои заметки:

Сначала XAML для двух DataGrids (первичного и вторичного, мы будем сортировать только вторую сетку «расширенных имен»:

        <TabControl Grid.Row="1" Name="tabControl1" VerticalAlignment="Top" Style="{StaticResource Section}" Margin="3" Padding="0" FontFamily="Arial" FontSize="10" BorderThickness="0" >
            <TabItem Name="tabCommon" Style="{StaticResource NameTab}">
                <DataGrid Name="grdCommonNames" SelectionChanged="grdCommonNames_SelectionChanged" PreviewKeyDown="grdCommonNames_PreviewKeyDown" Style="{StaticResource NameListGrid}" Focusable="False">
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding Name, NotifyOnTargetUpdated=True}" Width="SizeToCells" Header="Name" CellStyle="{StaticResource NameListCol}" SortDirection="Ascending"  />
                        <DataGridTextColumn Binding="{Binding Pronunciation, NotifyOnTargetUpdated=True}" Width="SizeToCells" Header="Pronunciation" CellStyle="{StaticResource NameListRightCol}"/>
                    </DataGrid.Columns>
                </DataGrid>
            </TabItem>
            <TabItem Name="tabExtended" Style="{StaticResource NameTab}">
                <DataGrid Name="grdExtendedNames" SelectionChanged="grdCommonNames_SelectionChanged" PreviewKeyDown="grdCommonNames_PreviewKeyDown" Style="{StaticResource NameListGrid}" >
                    <DataGrid.Columns>
                        <DataGridTextColumn Binding="{Binding Name, NotifyOnTargetUpdated=True}" Width="SizeToCells" Header="Name" CellStyle="{StaticResource NameListCol}" SortDirection="Descending" SortMemberPath="Name"/>
                        <DataGridTextColumn Binding="{Binding Pronunciation, NotifyOnTargetUpdated=True}" Width="SizeToCells" Header="Pronunciation" CellStyle="{StaticResource NameListRightCol}"/>
                    </DataGrid.Columns>
                </DataGrid>
            </TabItem>
        </TabControl>

Затем фрагмент кода для сортировки второй вкладки Datagrid после щелчка. Мы сортируем только в первый раз, поэтому здесь находится логическое значение. Таким образом, если они сортируют другой столбец вручную, он сохраняется, даже если они вернутся на первую вкладку, а затем повторно посетят вторую вкладку.

Здесь наш первый столбец в Datagrid называется «Имя». Фрагмент On Click:

        if (!extendSorted)
        {
            SortDescription extSort = new SortDescription("Name", ListSortDirection.Ascending);
            grdExtendedNames.Items.SortDescriptions.Add(extSort);
            extendSorted = true;
        }

Надеюсь, что это поможет кому-то еще отсортировать их сетку данных с помощью кода. Большинство других примеров, которые мы нашли, отлично работали для простых настроек, но в этой настройке с двумя таблицами данных с вкладками сортировка была нарушена.

person Lance Cleveland    schedule 07.10.2011

У меня была аналогичная проблема при вставке новой строки в DataGrid. Я решил эту проблему, обновив элементы DataGrid.

dataGrid.Items.Refresh (). Это восстанавливает также сортировку.
Не забудьте установить SortDirection в DataGridColumn (в данном случае это DataGridTextColumn)

Определение DataGrid:

<DataGrid x:Name="dgCustomers" ItemsSource="{Binding CustomerTable}" AutoGenerateColumns="False" CanUserDeleteRows="True">
        <DataGrid.Columns>
            <DataGridTextColumn Header="Kunden ID" Binding="{Binding Path=KundenID,Mode=TwoWay}" SortDirection="Ascending" />
            <DataGridTextColumn Header="Name" Binding="{Binding Path=Kundenname,Mode=TwoWay}"/>
    </DataGrid.Columns>
</DataGrid>

CS файл:

private void btnSavecustomerChanges_Click(object sender, RoutedEventArgs e)
{        
    try        
    {
        BL.UpdateCustomerChanges();
        dgCustomers.Items.Refresh();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Fehler beim Speichern", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}
person Pendl    schedule 24.07.2012

person    schedule
comment
Я предлагаю вам добавить небольшое повествование в предисловие к вашему коду, чтобы объяснить, что вы делаете и почему вы добавляете этот ответ на вопрос, которому два года. - person Rob; 27.01.2013