[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:如何启用/禁用复选框

DataGridCheckboxColumn 双向绑定

WPF DataGridCheckBoxColumn 绑定值后不能选中以及 能选中后,不能进行属性通知

如何在不需要额外点击的情况下使 DataGridCheckBoxColumn 可编辑?

WPF DataGridCheckBoxColumn检查/取消选中有时不起作用