2

我有一个 WPF DataGrid,它的第一列包含一个数字,即“排名”或“位置”。我想要的是,当我单击一列以根据该列对表格进行排序时,第一列保持原样。

例如:

职位名称 比赛积分 PPG
1约翰2 10 5
2 玛丽 3 12 4

当按游戏降序排序时,应变为

职位名称 比赛积分 PPG
1 玛丽 3 12 4
2约翰2 10 5

有没有办法做到这一点?DataColumn 似乎没有任何此类属性,并且 FreezeColumnsCount 仅始终将它们保留在视图中,但不会阻止它们与其余数据一起排序。

4

3 回答 3

3

我会为此使用 a ValueConverter。我不能确切地告诉你怎么做,但是,你要查看的是ItemContainerGeneratorDataGrid 上的属性。

向您的 ValueConverter添加一个DataGrid属性,以便您可以从 Convert 方法访问该属性。现在,在转换中,您需要调用ContainerFromItem以获取 UI 对象,然后IndexFromContainer获取行的索引。我相信你会遇到一些问题,但这应该让你开始。

这样做的好处是您不必自己进行排序。这将依赖于SortDescriptions添加到ICollectionViewDataGrid 使用的(如果您不绑定到一个,它会自动为您创建)。

编辑

这是请求的代码示例。我自己不需要这样做,但这是我要开始的地方。

以下是转换后的建议值的外观

public ItemPositionValueConverter : IValueConverter
{
    public DataGrid DataGrid { get; set; }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
        {
            return null;
        }

        if (DataGrid == null)
        {
            return null;
        }

        ItemContainerGenerator generator = DataGrid.ItemContainerGenerator;
        return generator.IndexFromContainer(generator.ContainerFromItem(value));
    }

    //you probably don't need ConvertBack put it is provided for completeness
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int? index = value as int?

        if (index == null)
        {
            return null
        }

        if (DataGrid == null)
        {
            return null;
        }

        ItemContainerGenerator generator = DataGrid.ItemContainerGenerator;
        return generator.ItemFromContainer(generator.ContainerFromIndex(index.Value));
    }
}

现在使用这个做类似的事情。

<UserControl>
    <UserControl.Resources>
        <ItemPositionValueConverter x:Key=ItemPositionValueConverter"
                                    DataGrid="{Binding ElementName=MyDataGrid}" />
    </UserControl.Resources>

    <DataGrid x:Name="MyDataGrid" ItemsSource="{Binding ....}">
        <DataGrid.Columns> 
            <DataGridTextColumn Header="Position"
                                Binding="{Binding Converter={StaticResource ItemPositionValueConverter}}"/>
        </DataGrid.Columns>
</UserControl>

请注意,使用此解决方案,无需手动将排序添加到 ICollectionView。单击列标题时,将自动应用排序。

**免责声明:此代码已经过测试,可能与描述的功能不完全相同。这里是提供者来演示所需的逻辑。因此,它可能包含拼写错误或错误。任何尝试使用此代码的人都应该执行自己的测试以验证它是否适合他们的需求。

于 2012-04-25T18:56:36.657 回答
3

http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/ffd7037d-dd77-44ec-9011-d0d43d5706aa/我刚刚找到了我在评论中建议的示例(来自 Adbie 的回答) :

<DataGrid LoadingRow="dg_LoadingRow">
    <DataGrid.RowHeaderTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=Header, RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}}" />
        </DataTemplate>
    </DataGrid.RowHeaderTemplate>
</DataGrid>


private void dg_LoadingRow(object sender, DataGridRowEventArgs e)
{
    e.Row.Header = (e.Row.GetIndex() + 1).ToString();
}


由 OP 编辑​​:
我刚刚验证它即使没有绑定也可以工作。cs 代码很好,但在 XAML 中你只需要做

<DataGrid LoadingRow="dg_LoadingRow" />
于 2012-04-25T23:21:25.083 回答
0

新答案:

所以我的最后一个答案显然不符合标准,我做了一些研究,看起来你可以像这样做你正在寻找的东西:

 Dim view As ICollectionView = CollectionViewSource.GetDefaultView(ListViewName.Items)
 view.SortDescriptions.Add(New SortDescription("Field To Sort By", 0))

在哪里

  • 'Field to Sort By' 是列名
  • # 方向 0 为升序,1 为降序

笔记:

  • 您必须在更改列表中同一列的排序顺序之间调用 view.SortDescriptions.Clear()
于 2012-04-25T20:15:55.653 回答