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.