Let me prefix this question by stating that I\'m very new to both C# and WPF.
I\'m trying to connect a collection of Boolean
values to a container conta
By the link that you provided, you could also use INotifyPropertyChanged extension to your CheckedListItem class, but thats if you dont want use ObservableCollection. It would be something like this:
public class CheckedListItem : INotifyPropertyChanged
{
private int _Id;
public int Id
{
get;
set; NotifyIfAnythingChanged("Id");
}
private string _Name;
public string Name
{
get;
set; NotifyIfAnythingChanged("Name");
}
private bool _IsChecked;
public bool IsChecked
{
get;
set; NotifyIfAnythingChanged("IsChecked");
}
private void NotifyIfAnythingChanged(String propName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Your listbox should be something like this:
<ListBox x:Name="MyListBox">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content={Binding Path=Name} IsChecked="{Binding Mode=TwoWay, Path=IsChecked}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
In your code behind you should initialize the ObservableCollection just once, because every change made into it will result into an UI update.
ObservableCollection<CheckedListItem> MyList = new ObservableCollection<CheckedListItem>();
MyListBox.ItemsSource = MyList;
Now every change made into MyList, such as Add(), Remove(), Etc. Will affect your UI.
Use IsChecked="{Binding}"
to bind the item of the collection directly.
<ListBox ItemsSource="{Binding MyBooleanCollection}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Mode=OneWay}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
However it is not possible to do bind to source with this method. Because the binding on the IsChecked
property of the CheckBox
doesn't the index of the item of the binding. So, it can't change the collection but only the item of the collection.
To get around that limitation, you can create a wrapper to the Boolean value:
public class Wrapper<T> : INotifyPropertyChanged
{
private T value;
public T Value
{
get { return value; }
set
{
{
this.value = value;
OnPropertyChanged();
}
}
}
public static implicit operator Wrapper<T>(T value)
{
return new Wrapper<T> { value = value };
}
public static implicit operator T(Wrapper<T> wrapper)
{
return wrapper.value;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Here is an exemple of usage:
public partial class MainWindow : Window
{
public ObservableCollection<Wrapper<bool>> MyBooleanCollection { get; private set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
MyBooleanCollection = new ObservableCollection<Wrapper<bool>>() { false, true, true, false, true };
}
}
And in the XAML:
<CheckBox IsChecked="{Binding Value}"/>
In the ItemTemplate
you may write
<CheckBox IsChecked="{Binding Path=.}"/>
or
<CheckBox IsChecked="{Binding Mode=OwnWay}"/>
which binds directly to the item object, i.e. the bool
value from the collection.
Note however that in either case the bound values in the collection will not be replaced when a CheckBox is checked or unchecked. In order to immediately update the collection when a CheckBox is clicked, your collection would have to contain objects with a boolean property to which IsChecked
is bound.
In your case this could be as simple as the following (as your question sounds like you don't need property change notifications):
public class BooleanHelper
{
public bool Value { get; set; }
}
The binding would now look like this:
<CheckBox IsChecked="{Binding Path=Value}"/>
The collection would now be an ObservableCollection<BooleanHelper>
and you would perhaps add items like this:
Items.Add(new BooleanHelper { Value = true });