简体   繁体   中英

How can I do this custom Select All function to work?

I have two connected classes: the Smartphone and the Model . The Smartphone contains a collection of Model that looks like this:

public class Smartphone
{
    public string BrandName { get; set; }
    public ObservableCollection<Model> Models { get; set; } = new ObservableCollection<Model>();
}

while the Model :

public class Smartphone
{
    public string ModelName { get; set; }
}

Then I added another property in the Model class:

public const string IsSelectPropertyName = "IsSelect";

private bool _isSelect = false;

public bool IsSelect
{
    get
    {
        return _isSelect ;
    }
    set
    {
        Set(IsSelectPropertyName, ref _isSelect , value);
    }
}

Then the SelectAll in the Smartphone class:

private bool _selectAll;

public bool SelectAll
{
    get
    {
        return _selectAll;
    }
    set
    {
        _selectAll = value;
        foreach (var item in Models)
        {
            item.IsSelect = value;
        }
        Set(() => SelectAll, ref _selectAll, value);
    }
}

The problem here is if one item is unchecked, the SelectAll is still checked. What I tried so far is having this function in Smartphone class:

public void CheckSelected()
{
    bool isUnchecked = Models.Select(item => item.IsSelect).AsQueryable().All(value => value == false);

    if (isUnchecked)
    {
        SelectAll = false;
    } else
    {
        SelectAll = true;
    }
}

However, if added into the IsSelect property in the Model class like this:

public const string IsSelectPropertyName = "IsSelect";

private bool _isSelect = false;

public bool IsSelect
{
    get
    {
        return _isSelect ;
    }
    set
    {
        Set(IsSelectPropertyName, ref _isSelect , value);
        if (Smartphone != null)
        {
            Smartphone.CheckSelected();
        }
    }
}

I got error like:

StackoverflowException

The problem is that you get in your SelectAll and IsSelect setters all the time, as you call CheckSelect() -> SelectAll -> IsSelect -> CheckSelect() in a loop.

One possible solution is to react in the setter of a property only when the value has actually be changed. The code might look like this:

get
{
    return _isSelect ;
}
set
{
    if (_isSelect == value)
        return; // don't do anything, nothing has been changed
    Set(IsSelectPropertyName, ref _isSelect , value);
    if (Smartphone != null)
    {
        Smartphone.CheckSelected();
    }
}

You will get inside the setter for the first time, but at the second time the field _isSelect has already been changed and you exit the setter with the return statement in the if() body. This also means that the following Smartphone.CheckSelected(); call is not executed, "breaking" the loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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