在我的wpf / c#项目中,我有3个维度的数据类型:长度,宽度和深度。当用户在datagrid中输入这些项时,使用转换器在第4列中计算此项的体积。我想要的是为此列启用排序。我试图将SortMemberPath放到Converter返回值,但这没有用。我认为这样做的一种方法是使用一个属性扩展我的数据类型,但如果可能的话,我想避免这种情况,只使用一些xaml / converter技术。
数据类型定义:
zsh
视图模型
public partial class packs
{
public packs()
{
}
public int id { get; set; }
public Nullable<decimal> length { get; set; }
public Nullable<decimal> width { get; set; }
public Nullable<decimal> depth { get; set; }
}
查看
public PacksVM
{
public ObservableCollection<packs> Packs{ get; set; }
...
}
和VolumeConverter
...
<DataGrid
x:Name="furniturePackagesGrid"
ItemsSource="{Binding Path=Packs}"
>
<DataGrid.Columns>
<DataGridTextColumn Header="Length"
Binding="{Binding length}"/>
<DataGridTextColumn Header="Width"
Binding="{Binding width}" />
<DataGridTextColumn Header="Depth"
Binding="{Binding depth}"/>
<DataGridTextColumn Header="Volume (m3)"
Binding="{Binding Mode=OneWay, Converter={StaticResource PackVolumeConverter}}"
IsReadOnly="True"
CanUserSort="True"
<!--I show no code for PackVolumeSortConverter because it is never called-->
SortMemberPath="{Binding Converter={StaticResource PackVolumeSortConverter}}"
/>
</DataGrid.Columns>
</DataGrid>
...
答案 0 :(得分:0)
就我在文档中看到的那样,SortMemberPath
在你的意义上是不可绑定的,但是应该包含一个字符串,其中包含要排序的属性的路径。
如果您不想使用卷属性对packs class
进行规范,我可以想出的唯一方法是为该类创建一个视图模型包装器:
public class VMPacks
{
public VMPacks(packs p)
{
Packs = p;
}
public packs Packs { get; private set; }
public decimal Volume
{
get
{
decimal volume = (Packs.length ?? default(decimal)) *
(Packs.width ?? default(decimal)) *
(Packs.depth ?? default(decimal)) / 1000000000;
return volume;
}
}
}
然后相应地调整列绑定,或者选择适当的属性和可能的实现INotifyPropertyChanged等。
修改强>
实际上可以通过以下方式进行自定义排序:
向DataGrid添加排序事件处理程序:
<DataGrid
x:Name="furniturePackagesGrid"
AutoGenerateColumns="False"
Sorting="furniturePackagesGrid_Sorting"
>
将SortMemberPath设置为虚拟值,如:
<DataGridTextColumn Header="Volume (m3)"
Binding="{Binding Mode=OneWay, Converter={StaticResource PackVolumeConverter}}"
IsReadOnly="True"
SortMemberPath="depth"
CanUserSort="True" />
这只是为了避免绑定表达式错误。
最后实现Sorting事件处理程序,如下所示:
private void furniturePackagesGrid_Sorting(object sender, DataGridSortingEventArgs e)
{
if (e.Column.DisplayIndex == 3)
{
DataGrid grid = sender as DataGrid;
List<packs> packs = grid.ItemsSource as List<packs>;
Func<packs, decimal> volume = (p) =>
{
decimal v = (p.length ?? default(decimal)) *
(p.width ?? default(decimal)) *
(p.depth ?? default(decimal)) / 1000000000;
return v;
};
packs.Sort((p1, p2) =>
{
if (p1 == p2)
return 0;
if (e.Column.SortDirection == ListSortDirection.Descending)
return Decimal.Compare(volume(p2), volume(p1));
return Decimal.Compare(volume(p1), volume(p2));
});
grid.ItemsSource = packs;
}
}
它要求将DataGrid.ItemsSource填充为List:
furniturePackagesGrid.ItemsSource = Enumerable.Range(0, 10000).Select(i => new packs
{
depth = 2 + i,
id = i,
length = 3 + i,
width = 4 + i,
}).ToList();