Reputation: 89
A have a list box with check boxes (I removed the part about alignment, width, margin as not related to the case):
<ListBox
ItemsSource ="{Binding SItemCollection}"
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Path=Item.Code}" IsChecked="{Binding IsChecked}"/>
</DataTemplate>
</ListBox.ItemTemplate>
I have a class SItem inside my ViewModel, which stores two fields - CachedStr which I get from Cache and a Boolean IsChecked which represents whether the item is checked or not (CachedStr object also has several fields (Name, Code etc), I've chosen to show the Code):
public class SItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public CachedStr Item { get; set; }
private bool _isChecked;
public bool IsChecked
{
get { return _isChecked; }
set
{
_isChecked = value;
NotifyPropertyChanged("IsChecked");
}
}
protected void NotifyPropertyChanged(string strPropertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(strPropertyName));
}
A have a Collection of SItems (SItemCollection), which fills my ListBox with items, some of which are ticked. This collection is outside the SItem class, it is inside my view model. I also have a set of all items (AvailableSItems) that should be available in the ListBox and a set of items that should be checked (ItemsToBeTicked) at the very beginning. This two sets contain objects of type CachedStr. By using those sets I get my SItemCollection:
public ObservableCollectionEx<SItem> SItemCollection
{
get
{
ObservableCollectionEx<SItem> strItems = new ObservableCollectionEx<SItem>();
this.AvailableSItems.ForEach(p =>
{
SItem item = new SItem();
item.Item = p;
item.IsChecked = false;
strItems.Add(item);
});
strItems.ForEach(p =>
{
if (this.ItemsToBeTicked.Contains(p.Item))
{
p.IsChecked = true;
}
else p.IsChecked = false;
}
);
return strItems;
}
}
The above-mentioned code works. But I also need a method which will get the final set of all ticked items (after, for example, pressing the button), and that's where I'm stuck. I do get a notifications when I tick or untick something.
Upvotes: 1
Views: 613
Reputation: 5623
The code currently creates a new instance of the collection in the get block. This has to be changed, otherwise the changes done in the UI will be reverted each time the get block is called.
Take the code which is currently in the get block, extract it to a method and use the return value of the method to set your SItemCollection
property.
In constructor for example:
SItemCollection = CreateInitialCollection();
And the property will be simplyfied to:
public ObservableCollectionEx<SItem> SItemCollection
{
get
{
return _sitemCollection;
}
set
{
if (_sitemCollection!= value)
{
_sitemCollection= value;
RaisePropertyChanged("SItemCollection");
}
}
}
ObservableCollectionEx<SItem> _sitemCollection;
When this is fixed (and if the binding to the IsChecked
property in SItem
works), you can use a Linq expression:
var checkedItems = SItemCollection.Where(item => item.IsChecked == true)
Upvotes: 1