WPF DataGrid:自动对DataGridTemplateColumn进行重新排序

时间:2010-10-24 12:30:40

标签: c# 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"); } }
}

6 个答案:

答案 0 :(得分:4)

我也在寻找答案。我找到了一个解决方案:(不满意,但......)

更新您的收藏后,您可以执行以下操作:

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

丑陋但确实有效。您将要存储整个集合,而不像我的第一个项目那样。

它的一个问题是DataGrid丢失了指示排序的标题,因此尽管它正确地解析,但不再选择列标题,并且箭头显示排序方向。

答案 1 :(得分:4)

我知道这是旧的但我也得到了这个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);
}

希望这有助于人们。

答案 2 :(得分:1)

2016年这些答案都不适合我。

经过一番尝试和错误后,我想出了这个并且似乎工作得很好:

dataGrid.Items.IsLiveSorting = true;

答案 3 :(得分:0)

我在VS2010下的C#WPF中有一个DataGrid,无论XAML设置如何都不会排序。出于某种原因,这个隐藏的DataGrid(在辅助选项卡上)存在排序顺序问题,其中主DataGrid在类似设置下很好。因此,我必须以图形方式对DataGrid进行排序。以下是我的笔记:

首先是两个DataGrids的XAML(主要和次要,我们只会对第二个“扩展名称”网格进行排序:

        <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中的第一列名为“Name”。 On Click片段:

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

希望能帮助其他人通过代码对数据网格进行排序。我们发现的大多数其他示例都可以用于简单的设置,但是在这个双数据网格选项卡式设置中,它将排序排除在外。

答案 4 :(得分:0)

在向DataGrid中插入新行时,我遇到了类似的问题。 我通过刷新DataGrid的项来解决了这个问题。

  

dataGrid.Items.Refresh()。这还恢复了排序。   
不要忘记在DataGridColumn上设置SortDirection(在这种情况下,它是一个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);
    }
}

答案 5 :(得分:0)

    If DataGridMain.Items.SortDescriptions.Count > 0 Then
        Dim vSortDescColl As New SortDescriptionCollection
        For Each vSortDesc In DataGridMain.Items.SortDescriptions
            vSortDescColl.Add(vSortDesc)
        Next
        DataGridMain.ItemsSource = Nothing
        DataGridMain.ItemsSource = vCallColl
        For Each vSortDesc In vSortDescColl
            DataGridMain.Items.SortDescriptions.Add(vSortDesc)
            For Each vColumn In DataGridMain.Columns
                If vColumn.SortMemberPath = vSortDesc.PropertyName Then
                    vColumn.SortDirection = vSortDesc.Direction
                    Exit For
                End If
            Next
        Next
    End If