繁体   English   中英

WPF MVVM中的绑定复选框问题

[英]Binding checkbox issue in WPF MVVM

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

我的问题 :更改复选框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}" />

这是我在图片中所做的。 在此处输入图片说明

关于我在哪里做错的任何建议? 谢谢。

我不知道您的viewmodel基类是什么,所以我只用了自己的。 我不知道您的Set()方法如何工作; 您可能需要一点适应性。 那一定是你的工作; 轮到你了。 我写这篇文章是因为向您解释逻辑要比编写代码花费更多的时间。 您应该阅读并理解该代码,而不是简单地将其粘贴到您的项目中。

请注意,我已经使用常规的C#命名约定编写了此代码。 布尔属性不再具有b前缀。 这意味着您必须从XAML绑定中的路径中删除该前缀。

还要注意,我将Rights_AllRights_AllAll并将其移至其他视图模型 现在它是Rights视图模型的成员。 这也将需要更改绑定。

您应该考虑将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;
                }
            }
        }
    }
}

这是我的解决方案的答案(在收到@Ed Plunkett和@zaitsman的建议后),我对Model中的一个类实现了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}" />

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM