Reputation: 317
EDIT : It now works ! Thanks to Alberto's detailed explanation, I bound IsChecked to a variable, and changed the button_1_click the way he wrote it
I'd like to return only the Content of checked boxes in a checkbox list that is defined this way in XAML :
<Grid>
<StackPanel Width="250" Height="80"></StackPanel>
<TextBox Name="ZoneText" Width="160" Height="20" Margin="12,215,330,76" Background="Bisque" />
<TextBox Name="ZoneValue" Width="160" Height="20" Margin="12,239,330,52" Background="Bisque" />
<ListBox Name="listBoxZone" ItemsSource="{Binding TheList}" Background="Azure" Margin="12,12,12,115">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Name="CheckBoxZone" Content="{Binding TheText}" Tag="{Binding TheValue}" Checked="CheckBoxZone_Checked" Margin="0,5,0,0" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Content="Validate" Height="44" HorizontalAlignment="Left" Margin="362,215,0,0" Name="button1" VerticalAlignment="Top" Width="123" Click="button1_Click" />
</Grid>
I'd like to be able to store all the content of the checked checkboxes in a list (when I press a button), but I can't seem to do it, here is what I've tried in C# :
public MainWindow()
{
InitializeComponent();
CreateCheckBoxList();
}
public class BoolStringClass
{
public string TheText { get; set; }
public int TheValue { get; set; }
}
public void CreateCheckBoxList()
{
TheList = new ObservableCollection<BoolStringClass>();
foreach (var line in File.ReadLines(path))
{
if (regex1.Match(line).Success)
TheList.Add(new BoolStringClass { TheText = "" + line, TheValue = false });
else
TheList.Add(new BoolStringClass { TheText = "" + line, TheValue = true });
this.DataContext = this;
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
foreach (CheckBox item in listBoxZone.Items)
{
List<string> selectedFOP = new List<String>();
if (item.IsChecked == true)
{
selectedFOP.Add(item.Content.ToString());
}
}
}
But I get an error that it is impossible to do a cast of an object whose type is 'BoolStringClass'
into a 'System.Windows.Controls.CheckBox'
. I guess I have to use listBoxZone.ItemTemplate
instead, but how can I access the checkboxes in it ?
Thank you
Upvotes: 1
Views: 883
Reputation: 2033
You have to change the TheValue type to a boolean
public class BoolStringClass
{
public string TheText { get; set; }
public bool? TheValue { get; set; }
}
And bind twoway the IsChecked property on the checkbox (you don't need to handle the checked changed event).
<CheckBox Name="CheckBoxZone" Content="{Binding TheText}" IsChecked="{Binding TheValue, Mode=TwoWay}" Margin="0,5,0,0" />
If the list can have different values when initialized you need to implement the INotifyPropertyChanged in the BoolStringClass so that checkboxes reflect the initial values (depending on your design this may not be necessary):
public class BoolStringClass : INotifyPropertyChanged
{
private bool? _thevalue;
public event PropertyChangedEventHandler PropertyChanged;
public string TheText { get; set; }
public bool? TheValue
{
get
{
return _thevalue;
}
set
{
_thevalue = value;
OnPropertyChanged("TheValue")
}
}
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
Also when creating the list in CreateCheckBoxList() use an ObservableCollection (if the number of checkboxes will not change dynamically but only on initialization here, you can use a normal list of BoolStringClass).
// use global variable
ObservableCollection<BoolStringClass> TheList;
public void CreateCheckBoxList()
{
//some code that creates a list
TheList = new ObservableCollection<BoolStringClass>() {
new BoolStringClass() {TheText = "Check1", TheValue = false},
new BoolStringClass() {TheText = "Check2", TheValue = true}
}
}
Then you can iterate on the list (also the copied list creation goes outside the loop!)
private void button1_Click(object sender, RoutedEventArgs e)
{
List<string> selectedFOP = new List<String>();
foreach (BoolStringClass item in TheList)
{
if (item.TheValue == true) selectedFOP.Add(item.ToString());
}
}
Probably you don't need to do this copy, depending on how your program is designed. If you really do, you can do it in one line with LINQ (add using System.LINQ):
private void button1_Click(object sender, RoutedEventArgs e)
{
var selectedFOP = TheList.Where(b => b.TheValue == true).ToList();
}
I'm doing it by hand so there could be minor syntax errors.
Upvotes: 1