首页 文章

WPF MVVM中的绑定复选框问题

提问于
浏览
0

我在从VM获取复选框IsChecked绑定值的值时遇到问题 . (我正在使用MVVM Light) .

My issue :当复选框IsChecked被更改时,它不会回激到我绑定到的VM属性 .

下面是代码 .

我有一个带有布尔值的类(在类文件中) .

public class Rights
{
    public bool bSales { get; set; }
    public bool bProduct { get; set; }
    public bool bZone { get; set; }
    public bool bPercentage { get; set; }
    public bool bUser { get; set; }
}

这是我的复选框将绑定到的属性(在VM中) .

private Rights user_Rights;
public Rights User_Rights
{
    get { return user_Rights; }
    set { Set(ref user_Rights, value); }
}

以下是我的“全选”复选框(在VM中)的属性 .

private bool? rights_All;
public bool? Rights_All
{
    get { return rights_All; }
    set
    {
        Set(ref rights_All, value);

        if (value == true)
        {
            User_Rights = new Rights() { bSales = true, bProduct = true, bPercentage = true, bZone = true, bUser = true };
        }
        else if(value == false)
        {
            User_Rights = new Rights() { bSales = false, bProduct = false, bPercentage = false, bZone = false, bUser = false };
        }
    }
}

最后,下面是我绑定的XAML .

<CheckBox Content="Sales PIC" IsChecked="{Binding User_Rights.bSales,Mode=TwoWay}" />
<CheckBox Content="Product" IsChecked="{Binding User_Rights.bProduct,Mode=TwoWay}" />
<CheckBox Content="Zone" IsChecked="{Binding User_Rights.bZone,Mode=TwoWay}" />
<CheckBox Content="Percentage" IsChecked="{Binding User_Rights.bPercentage}" />
<CheckBox Content="User" IsChecked="{Binding User_Rights.bUser}" />
<CheckBox Content="Select All" IsChecked="{Binding Rights_All}" />

这是我在图片中所做的 .
enter image description here

关于我哪里做错了的任何建议?谢谢 .

2 回答

  • 0

    我不知道你的 Set() 方法如何运作;这可能需要你的一点调整 . 那轮到你了 . 我这样写是因为向你解释逻辑比编写代码需要更长的时间 . 您应该阅读此代码并理解它,而不是简单地将其粘贴到您的项目中 .

    请注意,我使用传统的C#命名约定编写了这个 . 布尔属性不再具有 b 前缀 . 这意味着您必须从XAML中绑定的路径中删除该前缀 .

    另请注意,我将 Rights_All 重命名为 All ,并将其移至另一个viewmodel . 它现在是 Rights viewmodel的成员 . 这也需要更改绑定 .

    您应该考虑使用 Flags 枚举作为您的权利 . 这将简化代码,并使将来更容易添加其他权限 .

    public class Rights : ViewModelBase
    {
        private bool _sales;
        public bool Sales {
            get { return _sales; }
            set { SetRightFlag(ref _sales, value); }
        }
    
        private bool _product;
        public bool Product
        {
            get { return _product; }
            set { SetRightFlag(ref _product, value); }
        }
    
        private bool _zone;
        public bool Zone
        {
            get { return _zone; }
            set { SetRightFlag(ref _zone, value); }
        }
    
        private bool _percentage;
        public bool Percentage
        {
            get { return _percentage; }
            set { SetRightFlag(ref _percentage, value); }
        }
    
        private bool _user;
        public bool User
        {
            get { return _user; }
            set { SetRightFlag(ref _user, value); }
        }
    
        //  This logic needs to happen in five different setters, so I put it in a 
        //  method. 
        private bool SetRightFlag(ref bool field, bool value, [System.Runtime.CompilerServices.CallerMemberName] string propName = null)
        {
            if (field != value)
            {
                Set(ref field, value, propName);
                UpdateAll();
                return true;
            }
            return false;
        }
    
        //  I made this its own method as well, for cleanliness and clarity, even though 
        //  it's only called once. 
        protected void UpdateAll()
        {
            //  Don't call the All setter from here, because it has side effects.
            if (User && Percentage && Zone && Product && Sales)
            {
                _all = true;
                OnPropertyChanged(nameof(All));
            }
            else if (!User && !Percentage && !Zone && !Product && !Sales)
            {
                _all = false;
                OnPropertyChanged(nameof(All));
            }
            else if (All.HasValue)
            {
                _all = null;
                OnPropertyChanged(nameof(All));
            }
        }
    
        private bool? _all = null;
        public bool? All
        {
            get { return _all; }
            set {
                if (_all != value)
                {
                    Set(ref _all, value);
                    if (_all.HasValue)
                    {
                        User = Percentage = Zone = Product = Sales = (bool)_all;
                    }
                }
            }
        }
    }
    
  • 0

    以下是我的解决方案的答案(在得到@Ed Plunkett和@zaitsman的建议之后)我实现了INotifyProperty(通过使用MVVM Light方式)到我的模型中的一个类 .

    对于我的模型类 .

    public class Rights: ViewModelBase
    {
        public Rights()
        {
            _bSalesPIC = false;
            _bZone = false;
            ... (etc)
            _bAll = false;
        }
    
        private bool _bSalesPIC;
        public bool bSalesPIC
        {
            get { return _bSalesPIC; }
            set
            {
                Set(ref _bSalesPIC, value);
                TriggerAll();
            }
        }
    
        private bool _bZone;
        public bool bZone
        {
            get { return _bZone; }
            set
            {
                Set(ref _bZone, value);
                TriggerAll();
            }
        }
    
        private bool? _bAll;
        public bool? bAll
        {
            get { return _bAll; }
            set
            {
                Set(ref _bAll , value);
    
                if (value == true)
                {
                    _bSalesPIC = true;
                    _bZone = true;
                    RaisePropertyChanged("bSalesPIC");
                    RaisePropertyChanged("bZone");
                }
                else if (value == false)
                {
                    _bSalesPIC = false;
                    _bZone = false;
    
                    RaisePropertyChanged("bSalesPIC");
                    RaisePropertyChanged("bZone");
                }
            }
        }
    
        private void TriggerAll()
        {
            if (_bSalesPIC && _bZone && etc)
                bAll = true;
            else if (!_bSalesPIC && !_bZone && etc)
                bAll = false;
            else
                bAll = null;
        }
    

    对于我的VM .

    private Rights user_Rights;
        public Rights User_Rights
        {
            get { return user_Rights; }
            set { Set(ref user_Rights, value); }
        }
    

    而对于我的观点(XAML) .

    <CheckBox Content="Sales PIC" IsChecked="{Binding User_Rights.bSalesPIC}" />
        <CheckBox Content="Sales Input" IsChecked="{Binding User_Rights.bSalesInput}" />
        <CheckBox Content="Product" IsChecked="{Binding User_Rights.bProduct}" />
        <CheckBox Content="Zone" IsChecked="{Binding User_Rights.bZone}" />
        <CheckBox Content="Percentage" IsChecked="{Binding User_Rights.bPercentage}" />
        <CheckBox Content="User" IsChecked="{Binding User_Rights.bUser}" />
        <CheckBox Content="Select All" IsChecked="{Binding User_Rights.bAll}" />
    

相关问题