[DataGridCheckBoxColumn在属性更改时不会在MVVM中更新
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[DataGridCheckBoxColumn在属性更改时不会在MVVM中更新相关的知识,希望对你有一定的参考价值。
我正在使用的应用程序中有两个关键布尔值,以指示订单是否有效以待批准,然后指示该订单是否已被批准。我想要的是,当ObservableCollection的对象中的值更改时,复选框将在两列上更新,以便用户知道订单是否已准备好批准以及是否已经批准。
这些值会在模型中正确更新,并且视图模型中的批准按钮命令会按预期设置批准的布尔值,但是我无法获取复选框来动态更新。当前,它仅通过更改为其他视图然后再更改为订单视图来进行更新。
我仍在学习数据绑定和MVVM模型,因此我尝试了一些实验。到目前为止,我已经尝试了几种不同的方法来尝试获得我想要的行为,但是没有一个奏效。这是视图模型代码:
<UserControl x:Class="US_Wholesale_App_V2.Views.SPSOrderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:US_Wholesale_App_V2.Views"
xmlns:viewModels="clr-namespace:US_Wholesale_App_V2.ViewModels"
xmlns:models="clr-namespace:US_Wholesale_App_V2.Models"
mc:Ignorable="d"
d:DesignHeight="800" d:DesignWidth="1100">
<UserControl.Resources>
<DataTemplate DataType="x:Type viewModels:SPSLineVM">
<local:SPSLineView/>
</DataTemplate>
<DataTemplate DataType="x:Type viewModels:CustomerInfoVM">
<local:CustomerInfoView/>
</DataTemplate>
</UserControl.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="AUTO" MinWidth="312"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="AUTO"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Right"
Grid.Row="0"
Grid.Column="0">
<Button
Content="Lines"
Height="20"
Width="75"
Margin="5,5,5,10"
Command="Binding SPSNavCommand"
CommandParameter="Lines"/>
<Button
Content="Shipping"
Height="20"
Width="75"
Margin="5,5,5,10"
Command="Binding SPSNavCommand"
CommandParameter="Shipping"/>
</StackPanel>
<DataGrid
x:Name="OrderHeaderGrid"
AutoGenerateColumns="False"
Margin="5"
Grid.Row="1"
Grid.Column="0"
ItemsSource="Binding SpsData"
SelectedItem="Binding SelectedOrder, Mode=TwoWay"
CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn
Header="PO Number"
x:Name="PONumberCol"
Binding="Binding PONumber"/>
<DataGridTextColumn
Header="Customer"
x:Name="CustomerCol"
Binding="Binding Customer"/>
<DataGridTextColumn
Header="Retailer PO Number"
x:Name="RetailersPONumberCol"
Binding="Binding RetailersPONumber"/>
<DataGridTextColumn
Header="DC Code"
x:Name="DCCodeCol"
Binding="Binding DCCode"/>
<DataGridCheckBoxColumn
Binding="Binding IsValid, Mode=OneWay"
IsReadOnly="True"/>
<DataGridTemplateColumn
Header="Approve">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button
Content="Approve"
Command="Binding DataContext.ApproveButton, RelativeSource=RelativeSource FindAncestor, AncestorType=x:Type DataGrid"
CommandParameter="Binding SelectedOrder"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridCheckBoxColumn
Binding="Binding IsApproved, Mode=OneWay"
IsReadOnly="True"/>
</DataGrid.Columns>
</DataGrid>
<ContentControl
Grid.Row="1"
Grid.Column="1"
Margin="5">
<ContentControl Content="Binding SPSCurrentVM"/>
</ContentControl>
</Grid>
</UserControl>
如果有用,这里也是模型的代码。 RGLibrary项目只是我需要的通用类的库,例如SQL连接器或FTP方法。
using RGLibrary;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.ComponentModel;
using System.Threading.Tasks;
namespace US_Wholesale_App_V2.Models
public class SPSOrderModel : Observable_Object, IDataErrorInfo
private bool _IsApproved;
private string _PONumber;
private string _RetailersPONumber;
private string _PODate;
private string _ShipDate;
private string _CancelDate;
private string _POPurpose;
private string _POType;
private string _VendorNumber;
private string _Customer;
private string _DCCode;
private string _DepartmentNo;
private ObservableCollection<SPSLineModel> _Lines;
private BillingCustomerModel _BillingInfo;
private ShippingCustomerModel _ShippingInfo;
private ShippingChargesModel _Charges;
public bool IsApproved
get return _IsApproved;
set _IsApproved = value;
public string PONumber
get return _PONumber;
set _PONumber = value;
public string RetailersPONumber
get return _RetailersPONumber;
set _RetailersPONumber = value;
public string PODate
get return _PODate;
set _PODate = value;
public string ShipDate
get return _ShipDate;
set _ShipDate = value;
public string CancelDate
get return _CancelDate;
set _CancelDate = value;
public string POPurpose
get return _POPurpose;
set _POPurpose = value;
public string POType
get return _POType;
set _POType = value;
public string VendorNumber
get return _VendorNumber;
set _VendorNumber = value;
public string Customer
get return _Customer;
set _Customer = value;
public string DCCode
get return _DCCode;
set _DCCode = value;
public string DepartmentNo
get return _DepartmentNo;
set _DepartmentNo = value;
public ObservableCollection<SPSLineModel> Lines
get return _Lines;
set _Lines = value;
public BillingCustomerModel BillingInfo
get return _BillingInfo;
set _BillingInfo = value;
public ShippingCustomerModel ShippingInfo
get return _ShippingInfo;
set _ShippingInfo = value;
public ShippingChargesModel Charges
get return _Charges;
set _Charges = value;
public string Error
get
var errorMsg = new StringBuilder();
if (string.IsNullOrWhiteSpace(DepartmentNo))
errorMsg.AppendLine("The department number for this order cannot be blank");
if (string.IsNullOrWhiteSpace(PODate))
errorMsg.AppendLine("You must enter a purchase order date");
else if (!DateValidate("PODate", PODate))
errorMsg.AppendLine("The PO date format must be MM/DD/YYY");
if (string.IsNullOrWhiteSpace(CancelDate))
errorMsg.AppendLine("You must enter a cancellation date");
else if (!DateValidate("CancelDate", CancelDate))
errorMsg.AppendLine("The cancellation date format must be MM/DD/YYY");
if (string.IsNullOrWhiteSpace(ShipDate))
errorMsg.AppendLine("You must enter a shipment date");
else if (!DateValidate("ShipDate", ShipDate))
errorMsg.AppendLine("The shipment date format must be MM/DD/YYY");
if (string.IsNullOrWhiteSpace(DCCode))
errorMsg.AppendLine("You must enter a DC code");
if (Lines.Any(p => !p.IsValid))
errorMsg.AppendLine("You must correct all errors in the purchase order lines, or remove any lines with errors");
if (SumDispatch(Lines) < 1)
errorMsg.AppendLine("The total dispatch quantity must be at least 1");
return errorMsg.ToString();
public bool IsValid
get
bool check = true;
if (IsHeaderValid == false)
check = false;
if (BillingValid == false)
check = false;
if (ShippingValid == false)
check = false;
if (ChargesValid == false)
check = false;
if (LinesValid == false)
check = false;
return check;
public bool BillingValid
get
if (BillingInfo != null)
return BillingInfo.IsValid;
else
return false;
public bool ShippingValid
get
if (ShippingInfo != null)
return ShippingInfo.IsValid;
else
return false;
public bool ChargesValid
get
if (Charges != null)
return Charges.IsValid;
else
return false;
public bool LinesValid
get
bool check = true;
if (Lines.Any(l => l.IsValid == false))
check = false;
return check;
public bool IsHeaderValid
get
bool check = true;
if (string.IsNullOrWhiteSpace(PODate))
check = false;
if (!DateValidate("PODate", PODate))
check = false;
if (string.IsNullOrWhiteSpace(CancelDate))
check = false;
if (!DateValidate("CancelDate", CancelDate))
check = false;
if (string.IsNullOrWhiteSpace(ShipDate))
check = false;
if (!DateValidate("ShipDate", ShipDate))
check = false;
if (string.IsNullOrWhiteSpace(DCCode))
check = false;
if (Lines.Any(p => !p.IsValid))
check = false;
if (SumDispatch(Lines) < 1)
check = false;
if (string.IsNullOrWhiteSpace(DepartmentNo))
check = false;
return check;
public string this[string name]
get
string result = null;
if (name == "PODate")
if (string.IsNullOrWhiteSpace(PODate))
result = "You must enter a date";
else if (!DateValidate("PODate", PODate))
result = "Date format must be MM/DD/YYY";
if (name == "CancelDate")
if (string.IsNullOrWhiteSpace(CancelDate))
result = "You must enter a date";
else if (!DateValidate("CancelDate", CancelDate))
result = "Date format must be MM/DD/YYY";
if (name == "ShipDate")
if (string.IsNullOrWhiteSpace(ShipDate))
result = "You must enter a date";
else if (!DateValidate("ShipDate", ShipDate))
result = "Date format must be MM/DD/YYY";
if (name == "DCCode")
if (string.IsNullOrWhiteSpace(DCCode))
result = "You must enter a DC code";
return result;
private static bool DateValidate(string sender, object value)
bool check = true;
if (sender == "PODate" || sender == "CancelDate" || sender == "ShipDate")
string _date = value.ToString();
string _expression = @"(([0]\d)|(11|12))\/(([012]\d)|(30|31))\/(20)\d2";
Regex _Regex = new Regex(_expression);
Match _match = _Regex.Match(_date);
if (!_match.Success)
check = false;
return check;
private static int SumDispatch(ObservableCollection<SPSLineModel> lines)
int dispatchQty = 0;
foreach (SPSLineModel line in lines)
dispatchQty += line.DispatchQty;
return dispatchQty;
答案
正如问题中提到的最大,我需要在IsApproved和IsValid字段上实现PropertyChanged事件。对于IsApproved,这非常简单,因为我可以重用继承的Observable Object类中的事件:
以上是关于[DataGridCheckBoxColumn在属性更改时不会在MVVM中更新的主要内容,如果未能解决你的问题,请参考以下文章
wpf datagridcheckboxcolumn:如何启用/禁用复选框
WPF DataGridCheckBoxColumn 绑定值后不能选中以及 能选中后,不能进行属性通知