WPF-MVVM,Master - 带有计算列的详细数据网格。费率 * 数量 = 总计
WPF-MVVM, Master - Detail datagrid with calculated column. Rate * Quantity = Total
我有绑定到视图模型的数据输入表单。我遵循 EF 代码优先方法,详细信息表由我的模型中的可观察集合表示,如下所示。
public partial class item
{
public item()
{
orders = new ObservableCollection<order>();
}
}
一切正常,但在少数情况下,我有一个主条目,其中包含网格形式的详细信息。这是将 SelectedItem.Orders 绑定到详细信息网格的 xaml 部分。
<UserControl x:Class="ABCD.Views.itemView"
....
DataContext="{Binding itemMaster, Source={StaticResource Locator}}"
Height="Auto" Width="Auto">
<Grid>
<Grid.ColumnDefinitions.... />
<Grid.RowDefinitions..../>
<DataGrid AutoGenerateColumns="False" VerticalAlignment="Top" ItemsSource="{Binding items}" SelectedItem="{Binding SelectedItem}" Name="dgitems" HorizontalAlignment="Stretch" RowDetailsVisibilityMode="VisibleWhenSelected" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="ItemNameColumn" Binding="{Binding Path=ItemName}" Header="Item Name" Width="125" />
<DataGridTextColumn x:Name="ItemCodeColumn" Binding="{Binding Path=ItemCode}" Header="Item Code" Width="75" />
<DataGridTextColumn x:Name="StockColumn" Binding="{Binding Path=StockLevel}" Header="Stock" Width="60" />
</DataGrid.Columns>
</DataGrid>
<Label Grid.Column="3" Grid.Row="0" Margin="3,3,3,3" Content="Item Code" VerticalAlignment="Center" />
<TextBox Grid.Column="4" Grid.Row="0" HorizontalAlignment="Left" Margin="3,3,3,3" Name="ctrlItemCode" Text="{Binding Path=SelectedItem.ItemCode, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" Width="120" Height="Auto" VerticalContentAlignment="Center" />
<Label Grid.Column="3" Grid.Row="2" Margin="3,3,3,3" Content="Product Name" VerticalAlignment="Center" />
<TextBox Grid.Column="4" Grid.Row="2" HorizontalAlignment="Left" Margin="3,3,3,3" Name="ctrlProductName" Text="{Binding Path=SelectedItem.ItemName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" Width="120" Height="Auto" VerticalContentAlignment="Center" />
<DataGrid Grid.Column="2" Grid.Row="16" Grid.ColumnSpan="3" Height="145" AutoGenerateColumns="False" VerticalAlignment="Top" ItemsSource="{Binding SelectedItem.Orders}" Name="dgOrders" HorizontalAlignment="Stretch" >
<DataGrid.Columns>
<DataGridTemplateColumn Width="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox DisplayMemberPath="OrderNumber" SelectedValuePath="OrderId" ItemsSource="{Binding Path=DataContext.Orders, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" SelectedValue="{Binding Path=OrderId}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn x:Name="QtyColumn" Binding="{Binding Path=Quantity}" Header="Qty" Width="75" />
<DataGridTextColumn x:Name="PriceColumn" Binding="{Binding Path=Price}" Header="Price" Width="75" />
<DataGridTextColumn x:Name="TotalColumn" Binding="{Binding Path=Total}" Header="Total" Width="75" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
在这种情况下,我想在用户在网格中键入价格和数量后立即计算总数。我知道如果我们在视图模型中有相关的 属性 就可以处理。但就我而言,订单是项目模型中的一个集合。
提前致谢。
好的,
在论坛中搜索和寻求支持后,我找到了适合我的解决方案。只是张贴在这里,以便对某人有用。
简要介绍对我有用的最终答案。
可以做的是用视图模型包装每个实体。
因此,在那里使用该集合的数据网格将其 itermssource 绑定到 OrderVM 的可观察集合而不是 Order(实体类型)。
然后您可以用我的视图模型中的属性包装实体的属性,并在其中放置任何额外的业务逻辑,例如计算和引发 属性 当其中一个因素发生变化时在计算字段上发生变化。
根据这个建议,我的代码中的以下更改帮助我解决了问题;
如下所示的 OrderVM 集合;
public class OrderVM : baseViewModel
{
public OrderVM()
{ }
private order _order;
public order Order
{
get
{
return _order;
}
set
{
_order = value;
NotifyPropertyChanged();
}
}
public decimal Percentage
{
get
{
return (decimal)_order.Percentage; //Without passing the selectedOrder.Percentage like this, It doesn't work
}
set
{
_order.Percentage = value;
NotifyPropertyChanged();
calculate();
}
}
public decimal Qty
{
get
{
return (decimal)_order.Qty;
}
set
{
_order.Qty = value;
NotifyPropertyChanged();
calculate();
}
}
public decimal Total
{
get
{
return (decimal)_order.Total;
}
set
{
_order.Total = value;
NotifyPropertyChanged();
}
}
private void calculate()
{
_order.Total = _order.Price * _order.Qty;
NotifyPropertyChanged("Total");
}
}
itemVM (MainVM) 现在具有以下三个重要属性,
Orders = orderVM 的 ObservableCollection
SelectedItem //选择要编辑的项目
SelectedOrder //选择要编辑的订单
public class itemsVM : baseViewModel
{
private item _selectedItem;
private ObservableCollection<OrderVM> _orders;
public ObservableCollection<OrderVM> Orders
{
get
{
if (SelectedItem != null)
{
_orders = new ObservableCollection<OrderVM>();
foreach (Order ord in SelectedItem.Orders)
{
_orders.Add(new OrderVM { Order = ord });
}
return _orders;
}
else
return null;
}
set { _orders = value; }
}
//选中项属性
public 项 SelectedItem
{
得到
{
return_selectedItem;
}
放
{
_selectedItem = 值;
NotifyPropertyChanged();
NotifyPropertyChanged("CanModify");
NotifyPropertyChanged("Orders");
}
}
private OrderVM _selectedorder;
public OrderVM SelectedOrder
{
get
{
return _selectedorder;
}
set
{
_selectedorder = value;
NotifyPropertyChanged();
}
}
}
我的xaml如下;
<DataGrid Grid.Column="2" Grid.Row="16" Grid.ColumnSpan="3" Height="145" AutoGenerateColumns="False" VerticalAlignment="Top"
ItemsSource="{Binding Orders}" SelectedItem="{Binding SelectedOrder}" Name="dgOrders" HorizontalAlignment="Stretch" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="QtyColumn" Binding="{Binding Path=Qty}" Header="Qty" Width="75" />
<DataGridTextColumn x:Name="PriceColumn" Binding="{Binding Path=Price}" Header="Price" Width="75" />
<DataGridTextColumn x:Name="TotalColumn" Binding="{Binding Path=Total}" Header="Price" Width="75" />
</DataGrid.Columns>
</DataGrid>
完整的对话可以在Conversation at MSDN Forums
找到
我有绑定到视图模型的数据输入表单。我遵循 EF 代码优先方法,详细信息表由我的模型中的可观察集合表示,如下所示。
public partial class item
{
public item()
{
orders = new ObservableCollection<order>();
}
}
一切正常,但在少数情况下,我有一个主条目,其中包含网格形式的详细信息。这是将 SelectedItem.Orders 绑定到详细信息网格的 xaml 部分。
<UserControl x:Class="ABCD.Views.itemView"
....
DataContext="{Binding itemMaster, Source={StaticResource Locator}}"
Height="Auto" Width="Auto">
<Grid>
<Grid.ColumnDefinitions.... />
<Grid.RowDefinitions..../>
<DataGrid AutoGenerateColumns="False" VerticalAlignment="Top" ItemsSource="{Binding items}" SelectedItem="{Binding SelectedItem}" Name="dgitems" HorizontalAlignment="Stretch" RowDetailsVisibilityMode="VisibleWhenSelected" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="ItemNameColumn" Binding="{Binding Path=ItemName}" Header="Item Name" Width="125" />
<DataGridTextColumn x:Name="ItemCodeColumn" Binding="{Binding Path=ItemCode}" Header="Item Code" Width="75" />
<DataGridTextColumn x:Name="StockColumn" Binding="{Binding Path=StockLevel}" Header="Stock" Width="60" />
</DataGrid.Columns>
</DataGrid>
<Label Grid.Column="3" Grid.Row="0" Margin="3,3,3,3" Content="Item Code" VerticalAlignment="Center" />
<TextBox Grid.Column="4" Grid.Row="0" HorizontalAlignment="Left" Margin="3,3,3,3" Name="ctrlItemCode" Text="{Binding Path=SelectedItem.ItemCode, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" Width="120" Height="Auto" VerticalContentAlignment="Center" />
<Label Grid.Column="3" Grid.Row="2" Margin="3,3,3,3" Content="Product Name" VerticalAlignment="Center" />
<TextBox Grid.Column="4" Grid.Row="2" HorizontalAlignment="Left" Margin="3,3,3,3" Name="ctrlProductName" Text="{Binding Path=SelectedItem.ItemName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" Width="120" Height="Auto" VerticalContentAlignment="Center" />
<DataGrid Grid.Column="2" Grid.Row="16" Grid.ColumnSpan="3" Height="145" AutoGenerateColumns="False" VerticalAlignment="Top" ItemsSource="{Binding SelectedItem.Orders}" Name="dgOrders" HorizontalAlignment="Stretch" >
<DataGrid.Columns>
<DataGridTemplateColumn Width="120">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox DisplayMemberPath="OrderNumber" SelectedValuePath="OrderId" ItemsSource="{Binding Path=DataContext.Orders, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" SelectedValue="{Binding Path=OrderId}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTextColumn x:Name="QtyColumn" Binding="{Binding Path=Quantity}" Header="Qty" Width="75" />
<DataGridTextColumn x:Name="PriceColumn" Binding="{Binding Path=Price}" Header="Price" Width="75" />
<DataGridTextColumn x:Name="TotalColumn" Binding="{Binding Path=Total}" Header="Total" Width="75" />
</DataGrid.Columns>
</DataGrid>
</Grid>
</UserControl>
在这种情况下,我想在用户在网格中键入价格和数量后立即计算总数。我知道如果我们在视图模型中有相关的 属性 就可以处理。但就我而言,订单是项目模型中的一个集合。
提前致谢。
好的, 在论坛中搜索和寻求支持后,我找到了适合我的解决方案。只是张贴在这里,以便对某人有用。
简要介绍对我有用的最终答案。 可以做的是用视图模型包装每个实体。 因此,在那里使用该集合的数据网格将其 itermssource 绑定到 OrderVM 的可观察集合而不是 Order(实体类型)。
然后您可以用我的视图模型中的属性包装实体的属性,并在其中放置任何额外的业务逻辑,例如计算和引发 属性 当其中一个因素发生变化时在计算字段上发生变化。
根据这个建议,我的代码中的以下更改帮助我解决了问题; 如下所示的 OrderVM 集合;
public class OrderVM : baseViewModel
{
public OrderVM()
{ }
private order _order;
public order Order
{
get
{
return _order;
}
set
{
_order = value;
NotifyPropertyChanged();
}
}
public decimal Percentage
{
get
{
return (decimal)_order.Percentage; //Without passing the selectedOrder.Percentage like this, It doesn't work
}
set
{
_order.Percentage = value;
NotifyPropertyChanged();
calculate();
}
}
public decimal Qty
{
get
{
return (decimal)_order.Qty;
}
set
{
_order.Qty = value;
NotifyPropertyChanged();
calculate();
}
}
public decimal Total
{
get
{
return (decimal)_order.Total;
}
set
{
_order.Total = value;
NotifyPropertyChanged();
}
}
private void calculate()
{
_order.Total = _order.Price * _order.Qty;
NotifyPropertyChanged("Total");
}
}
itemVM (MainVM) 现在具有以下三个重要属性, Orders = orderVM 的 ObservableCollection SelectedItem //选择要编辑的项目 SelectedOrder //选择要编辑的订单
public class itemsVM : baseViewModel
{
private item _selectedItem;
private ObservableCollection<OrderVM> _orders;
public ObservableCollection<OrderVM> Orders
{
get
{
if (SelectedItem != null)
{
_orders = new ObservableCollection<OrderVM>();
foreach (Order ord in SelectedItem.Orders)
{
_orders.Add(new OrderVM { Order = ord });
}
return _orders;
}
else
return null;
}
set { _orders = value; }
}
//选中项属性 public 项 SelectedItem { 得到 { return_selectedItem; } 放 { _selectedItem = 值; NotifyPropertyChanged(); NotifyPropertyChanged("CanModify"); NotifyPropertyChanged("Orders"); } }
private OrderVM _selectedorder;
public OrderVM SelectedOrder
{
get
{
return _selectedorder;
}
set
{
_selectedorder = value;
NotifyPropertyChanged();
}
}
}
我的xaml如下;
<DataGrid Grid.Column="2" Grid.Row="16" Grid.ColumnSpan="3" Height="145" AutoGenerateColumns="False" VerticalAlignment="Top"
ItemsSource="{Binding Orders}" SelectedItem="{Binding SelectedOrder}" Name="dgOrders" HorizontalAlignment="Stretch" >
<DataGrid.Columns>
<DataGridTextColumn x:Name="QtyColumn" Binding="{Binding Path=Qty}" Header="Qty" Width="75" />
<DataGridTextColumn x:Name="PriceColumn" Binding="{Binding Path=Price}" Header="Price" Width="75" />
<DataGridTextColumn x:Name="TotalColumn" Binding="{Binding Path=Total}" Header="Price" Width="75" />
</DataGrid.Columns>
</DataGrid>
完整的对话可以在Conversation at MSDN Forums
找到