Wpf DataGrid计算两个数据绑定单元格中的值之间的差值
在我的小应用程序中,我有一个绑定到测量对象列表的DataGrid(参见屏幕截图)。测量只是一个具有两个属性的数据容器:日期和反气体(浮动)。 每个测量对象代表我在特定日期的耗气量 测量值列表绑定到DataGrid,如下所示:Wpf DataGrid计算两个数据绑定单元格中的值之间的差值,wpf,datagrid,binding,Wpf,Datagrid,Binding,在我的小应用程序中,我有一个绑定到测量对象列表的DataGrid(参见屏幕截图)。测量只是一个具有两个属性的数据容器:日期和反气体(浮动)。 每个测量对象代表我在特定日期的耗气量 测量值列表绑定到DataGrid,如下所示: <DataGrid ItemsSource="{Binding Path=Measurements}" AutoGenerateColumns="False"> <DataGrid.Columns>
<DataGrid ItemsSource="{Binding Path=Measurements}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Date" Binding="{Binding Path=Date, StringFormat={}{0:dd.MM.yyyy}}" />
<DataGridTextColumn Header="Counter Gas" Binding="{Binding Path=ValueGas, StringFormat={}{0:F3}}" />
</DataGrid.Columns>
</DataGrid>
现在我的问题是:)
我想在“计数器气体”列旁边有另一列,显示实际计数器值和最后一个计数器值之间的差值
例如,此附加列应计算2月13日和2月6日的值之间的差值=>199.789-187.115=15.674
实现这一目标的最佳方式是什么?我想避免在测量类中进行任何计算,这些计算应该只保存数据。我更喜欢DataGrid来处理计算。
那么,有没有一种方法可以添加另一列,只计算to值之间的差异?可能使用某种转换器和极限绑定;D
旁白:也许有个名声更好的人可以嵌入这个截图。谢谢:)极端绑定?没问题
<Window.Resources>
<local:ItemsDifferenceConverter x:Key="ItemsDifferenceConverter"/>
</Window.Resources>
<DataGrid ItemsSource="{Binding Path=Measurements}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Date" Binding="{Binding Path=Date, StringFormat={}{0:dd.MM.yyyy}}" />
<DataGridTextColumn Header="Counter Gas" Binding="{Binding Path=ValueGas, StringFormat={}{0:F3}}" />
<DataGridTextColumn Header="Difference">
<DataGridTextColumn.Binding>
<MultiBinding Converter="{StaticResource ItemsDifferenceConverter}" Mode="OneWay">
<Binding Path="."/>
<Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGrid}}" Path="ItemsSource"/>
</MultiBinding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
非常感谢你!这就像一个符咒:)但正如你所说,有一些缺点。但没问题,这么小的解决方案是gerate的!只是出于兴趣:在这种情况下,您将如何实现中间视图模型?@justMe我在答案的和处添加了我的示例。它使用CollectionView并观察更改。@Vortex:在这种情况下如何实现相同的视图模型?我有一个datagrid,它垂直显示数据库中的一个表,如下所示:分数| 75 | 100。我必须在分数下面添加一个名为Difference的新行,该行应显示或返回值75和100之间的差值。(这只是一个例子)(P.S:差异中没有负值)。。这真的很有帮助。。Thanks@Buba1947如果需要行而不是列,则应向集合中添加新项。像
someCollection.Add(新的SomeModel{Title=“Difference”,Score75=null,Score100=(scoresItem.Score100-scoresItem.Score75)})代码>。我想如果你为你想要的表格做一个屏幕截图,然后再做一个单独的问题会更好。@vortex:我已经把这个问题贴在这里了。有空的时候请看一看。非常感谢。
class ItemsDifferenceConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType,
object parameter, CultureInfo culture)
{
if (values.Length != 2)
return null;
var item = values[0] as Measurement;
var collection = values[1] as IEnumerable<Measurement>;
if (item == null || collection == null)
return null;
var list = collection.OrderBy(v => v.Date).ToList(); //it will be easier to find a previous date
var itemIndex = list.IndexOf(item);
if (itemIndex == 0) //First item
return null;
var diff = item.ValueGas - list[itemIndex - 1].ValueGas;
return (diff > 0 ? "+" : "") + diff.ToString();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
/// <summary>
/// Main ViewModel, contains items for DataGrid
/// </summary>
public class MeasurementListViewModel
{
public MeasurementListViewModel(IEnumerable<Measurement> measurements)
{
this.Items = new ObservableCollection<MeasurementViewModel>(measurements.Select(m=>new MeasurementViewModel(m)));
this.Measurements = (ListCollectionView)CollectionViewSource.GetDefaultView(this.Items);
this.Items.CollectionChanged += new NotifyCollectionChangedEventHandler(Items_CollectionChanged);
foreach(var m in this.Items)
m.PropertyChanged += new PropertyChangedEventHandler(Item_PropertyChanged);
}
//Date or Value were changed
void Item_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
//Update the collection view if refresh isn't possible
if (this.Measurements.IsEditingItem)
this.Measurements.CommitEdit();
if (this.Measurements.IsAddingNew)
this.Measurements.CommitNew();
this.Measurements.Refresh();
}
//Items were added or removed
void Items_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
//Attach the observer for the properties
if (e.NewItems != null)
foreach (var vm in e.NewItems.OfType<MeasurementViewModel>())
vm.PropertyChanged += Item_PropertyChanged;
//Refresh when it is possible
if(!this.Measurements.IsAddingNew && !this.Measurements.IsEditingItem)
this.Measurements.Refresh();
}
private ObservableCollection<MeasurementViewModel> Items { get; set; }
public ListCollectionView Measurements { get; set; }
}
/// <summary>
/// Wraps Measurement class and provide notification of changes
/// </summary>
public class MeasurementViewModel
{
public MeasurementViewModel()
{
this.Model = new Measurement();
}
public MeasurementViewModel(Measurement m)
{
this.Model = m;
}
public Measurement Model { get; private set; }
public DateTime Date
{
get { return this.Model.Date; }
set
{
this.Model.Date = value;
OnPropertyChanged("Date");
}
}
public double ValueGas
{
get { return this.Model.ValueGas; }
set
{
this.Model.ValueGas = value;
OnPropertyChanged("ValueGas");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
class ItemsDifferenceConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType,
object parameter, CultureInfo culture)
{
var item = values[0] as MeasurementViewModel;
var view = values[1] as ICollectionView;
if (item == null || view == null)
return null;
var list = view.SourceCollection.OfType<MeasurementViewModel>().OrderBy(v => v.Date).ToList(); //it will be easier to find a previous date
var itemIndex = list.IndexOf(item);
if (itemIndex == 0) //First item
return null;
var diff = item.ValueGas - list[itemIndex - 1].ValueGas;
return (diff > 0 ? "+" : "") + diff.ToString();
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new Exception("The method or operation is not implemented.");
}
}
<DataGrid ItemsSource="{Binding Path=Measurements}" AutoGenerateColumns="False"
CanUserAddRows="True">
<DataGrid.Columns>
<DataGridTextColumn Header="Date" Binding="{Binding Path=Date, StringFormat={}{0:dd.MM.yyyy}}" />
<DataGridTextColumn Header="Counter Gas" Binding="{Binding Path=ValueGas, StringFormat={}{0:F3}}" />
<DataGridTextColumn Header="Difference">
<DataGridTextColumn.Binding>
<MultiBinding Converter="{StaticResource ItemsDifferenceConverter}" Mode="OneWay">
<Binding Path="."/>
<Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGrid}}" Path="ItemsSource"/>
</MultiBinding>
</DataGridTextColumn.Binding>
</DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>