Am Using the checkbox in listbox items, how to get the selected checkboxes from the list
<ListBox ItemsSource="{Binding NameList}" HorizontalAlignment="Left" Margin="16,68,0,12" Name="listBox1" Width="156" IsEnabled="True" SelectionMode="Multiple" Focusable="True" IsHitTestVisible="True" IsTextSearchEnabled="False" FontSize="12" Padding="5" SelectionChanged="listBox1_SelectionChanged">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Content="{Binding Path=CNames}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
I tried to loop thru the selected items in the listboxitems, but it throws exception in listboxitem
private void btnSelected(object sender, RoutedEventArgs e)
{
foreach (ListBoxItem item in listBox1.Items)
{
if (item.ToString() == "true")
{
MessageBox.Show(item.Content.ToString());
}
}
}
You could move the data context for each of these items away from the UI and create an ObservableCollection of objects
public ObservableCollection<CheckedItem> List { get;set;}
public class CheckedItem : INotifyPropertyChanged
{
private bool selected;
private string description;
public bool Selected
{
get { return selected; }
set
{
selected = value;
OnPropertyChanged("Selected");
}
}
public string Description
{
get { return description; }
set
{
description = value;
OnPropertyChanged("Description");
}
}
/* INotifyPropertyChanged implementation */
}
Then in your ListBox ItemTemplate
<ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=Selected}"
Content={Binding Path=Description}" />
</DataTemplate>
</ItemTemplate>
Your selected items are now available in the ObservableCollection rather than looping through UI elements
Have your template like this
<ListBox.ItemTemplate>
<DataTemplate>
........
<CheckBox Content=""
IsChecked="{Binding IsSelected, Mode=TwoWay,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListViewItem}}}" />
..........
<!-- Use Other UIElements to Show your Data -->
then the above binding will sync two way with your models isSelected and list view selection, then in code use SelectedItems.
For Each s As myPoco In myListView1.SelectedItems
' do something here with
Next
I would suggest this code:
private void save_Click(object sender, RoutedEventArgs e)
{
foreach (CheckBox item in list1.Items)
{
if (item.IsChecked)
{
MessageBox.Show(item.Content.ToString());
}
}
}
Related
I have a Listbox which is bound to a DataTemplate that has another Listbox on it.
On DataTemplate there is a button that I want to use for adding items to DataTemplate ListBox, but I can't find a solution to do this.
Here is my listbox:
<Button Width="200" Content="Add Question" x:Name="btnAddQuestion" Click="btnAddQuestion_Click"/>
<StackPanel Orientation="Horizontal">
<ListBox Margin="5" x:Name="lvQuestions" ItemTemplate="{StaticResource TemplateQuestionTitle}">
</ListBox>
</StackPanel>
And this is DataTemplate:
<DataTemplate x:Key="TemplateQuestionTitle">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBox materialDesign:HintAssist.Hint="Enter question" MinWidth="200" Style="{StaticResource MaterialDesignFloatingHintTextBox}"/>
<Button Content="+" Command="{Binding Source={x:Reference ThisPage},Path=DataContext.Command}" />
</StackPanel>
<ListBox ItemsSource="{Binding MyItems}" MinHeight="50">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox>
</TextBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
This is code behind on my page:
public partial class UIBuilder:Window
{
private CommandVm _commandVm;
public UIBuilder()
{
InitializeComponent();
_commandVm = new CommandVm();
DataContext = _commandVm;
}
private void btnAddQuestion_Click(object sender, RoutedEventArgs e)
{
lvQuestions.Items.Add(null);
}
}
I have implemented this code on my ViewModel in order to add items to datatemplate ListBox:
public class CommandVm
{
public ObservableCollection<TextBox> MyItems { get; set; }
public CommandVm()
{
MyItems = new ObservableCollection<TextBox>();
Command = new RelayCommand<TextBox>(Execute);
}
private void Execute(TextBox textBox)
{
MyItems .Add(textBox);
}
public ICommand Command { get; set; }
}
I use to catch the Execute() function on button "+" click command, but my code doesn't add any ListBox item.
MyItems is a property of the parent view model which means that you should bind to it like this:
<ListBox ItemsSource="{Binding DataContext.MyItems,
RelativeSource={RelativeSource AncestorType=Window}}" MinHeight="50">
This also means that you are using one single collection of items for all questions. Besides this obvious design flaw, a view model should not contain any TextBox elements. This basically breaks what the MVVM pattern is all about.
What you should do to make this example MVVM compliant is to create a Question class that has a collection of items, e.g.:
public class Question
{
public Question()
{
AddAnswerCommand = new RelayCommand<object>(Execute);
}
private void Execute(object obj)
{
Items.Add(new Answer());
}
public ObservableCollection<Answer> Items { get; }
= new ObservableCollection<Answer>();
public ICommand AddAnswerCommand { get; }
}
public class Answer { }
The window's view model should then have a collection of questions:
public class CommandVm
{
public CommandVm()
{
AddQuestionCommand = new RelayCommand<object>(Execute);
}
public ObservableCollection<Question> Questions { get; }
= new ObservableCollection<Question>();
public ICommand AddQuestionCommand { get; }
private void Execute(object obj)
{
Questions.Add(new Question());
}
}
The view and the bindings could then be defined like this:
<Window.Resources>
<DataTemplate x:Key="TemplateQuestionTitle">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<TextBox MinWidth="200" />
<Button Content="+" Command="{Binding AddAnswerCommand}" />
</StackPanel>
<ListBox ItemsSource="{Binding Items}" MinHeight="50">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBox />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</DataTemplate>
</Window.Resources>
<StackPanel>
<Button Width="200" Content="Add Question" Command="{Binding AddQuestionCommand}"/>
<ListBox Margin="5"
ItemsSource="{Binding Questions}"
ItemTemplate="{StaticResource TemplateQuestionTitle}" />
</StackPanel>
This setup lets you add individual elements to each separate question.
I've got a question, I have a list of checkbox in combobox box and it looks like this:
<StackPanel Orientation="Vertical" DataContext="{Binding CandidateEntity}">
<StackPanel Orientation="Horizontal">
<ComboBox ItemsSource="{Binding DataContext.SkillSetEntities, ElementName=CrudCandidate }"
IsEditable="True" IsReadOnly="True" Text="Umiejętności">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</StackPanel>
Now I also have a collection of skillset objects in binded item source (CandidateEntity.SkillSets), now how can I check those checkboxes that are in my collection of skillset objects?
I want to create a edition for CandidateEntity object in form and part of that edition is list of skillset that is represented in combobox.
EDIT:
I have solved problem by adding to skillset model prop:
private bool _isSelected = false;
[NotMapped]
public bool IsSelected
{
get
{
return this._isSelected;
}
set
{
_isSelected = value;
}
}
And then in view model:
private List<SkillSet> GetSkillSets()
{
var skillsetList = this._catalog.SkillSets.ToList();
var candidateSkillsetList = this.CandidateEntity.SkillSets.ToList();
foreach (SkillSet skillset in skillsetList)
{
foreach (SkillSet candidateSkillset in candidateSkillsetList)
{
if (skillset.id == candidateSkillset.id)
{
skillset.IsSelected = true;
}
}
}
return skillsetList;
}
and in checkbox in wpf:
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsSelected}"/>
BUT I am pretty sure there must be easier way to handle that, is there?
I have a ListBox which creates a TextBlock for every item in my Dictionary and I need to create a click event and have the possibility to get anything from the TextBlock (Tag in example).
Is this even possible? I found many similar questions, but nothing that would work for me.
My ListBox:
<ListBox x:Name="listbox">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Tag="{Binding Path=Key}"
Text="{Binding Path=Value.ImieNazwisko}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
To simplify things lets say your dictionary is some thing like this :
public Dictionary<string,MyItem> MyDictionary { get; set; }
and your model :
public class MyItem
{
public string ImieNazwisko { get; set; }
}
and you set the ListBox ItemSource from the code behind like this :
InitializeComponent();
MyDictionary = new Dictionary<string, MyItem>()
{
{"key1",new MyItem() {ImieNazwisko = "one"} },
{"key2",new MyItem() {ImieNazwisko = "two"} }
};
Listbox.ItemsSource = MyDictionary;
You could simply handle the MouseDown event and retrieve the Tag property from the sender:
<ListBox x:Name="Listbox" Margin="225,0,0,0" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Tag="{Binding Path=Key}" Text="{Binding Path=Value.ImieNazwisko}" MouseDown="UIElement_OnMouseDown"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
the handler
private void UIElement_OnMouseDown(object sender, MouseButtonEventArgs e)
{
var tag=(sender as TextBlock).Tag;
}
I have a listbox with a datatemplate that contains a checkbox and textblock. How do I get the multiselection working with the checkbox in the template so that selection is based on the isChecked property of the checkbox? The need I have is to have a dropdown with checkboxes that could cater for multiselection. This is what I have sofar. Please feel free to give suggestions on where I could better this code as this is the whole point.
XAML:
<DataTemplate x:Key="WorkCentreItem">
<StackPanel Orientation="Horizontal">
<CheckBox Content="{Binding WorkCentre}" IsChecked="{Binding IsChecked}"/>
<TextBlock Text=" - "/>
<TextBlock Text="{Binding Description}"/>
</StackPanel>
</DataTemplate>
<telerik:RadListBox
SelectionMode="Multiple"
Grid.Row="2"
Grid.ColumnSpan="2"
Grid.RowSpan="1"
Margin="-1,20,0,3"
ItemsSource="{Binding SampleWorkCentres}"
ItemTemplate="{StaticResource WorkCentreItem}"
ScrollViewer.CanContentScroll="True"
SelectionChanged="RadListBox_SelectionChanged">
</telerik:RadListBox>
Model:
#region SampleWorkCentres
public const string SampleWorkCentresPropertyName = "SampleWorkCentres";
private ObservableCollection<BomWorkCentre> _sampleWorkCentres;
public ObservableCollection<BomWorkCentre> SampleWorkCentres
{
get
{
if (this._sampleWorkCentres == null)
{
using (SysproKitIssueEntities db = new SysproKitIssueEntities())
{
this._sampleWorkCentres = new ObservableCollection<BomWorkCentre>(db.BomWorkCentres.Select(x => x).Distinct().ToList());
}
}
return this._sampleWorkCentres;
}
set
{
if (this._sampleWorkCentres == value)
{
return;
}
this._sampleWorkCentres = value;
this.RaisePropertyChanged(SampleWorkCentresPropertyName);
}
}
#endregion
#region SelectedWorkCentres
public const string SelectedWorkCentresPropertyName = "SelectedWorkCentres";
private ObservableCollection<BomWorkCentre> _selectedWorkCentres = new ObservableCollection<BomWorkCentre>();
public ObservableCollection<BomWorkCentre> SelectedWorkCentres
{
get
{
return this._selectedWorkCentres;
}
set
{
if (this._selectedWorkCentres != value)
{
this._selectedWorkCentres = value;
}
this._sampleGridItems = null;
this.RaisePropertyChanged(SampleGridItemsPropertyName);
this.RaisePropertyChanged(SelectedWorkCentresPropertyName);
}
}
#endregion
You should data bind the Checkbox.IsChecked to the ListBoxItem.IsSelected Property using a RelativeSource Binding:
<CheckBox Content="{Binding WorkCentre}" IsChecked="{Binding IsSelected,
RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}}" />
Sorry for the vague description, I can't think of a better way to put it.
Let's say that my ViewModel has a property as follows:
public List<MyClass> SubSystems { get; set; }
and the SubSystems class:
public class SubSystem
{
public string Name { get; set; }
public bool IsSelected { get; set; }
}
In the view, I'd like to bind the SubSystems property to, what I think would be, a list of checkboxes where the IsChecked and Name properties of the CheckBox is bound to the their respective properties, IsChecked for IsSelected and Content for Name.
I know I can make a ListBox in the XAML, but I'm not sure how I'd go about doing this using binding and a collection..
Thanks for the help!
Edit -
Here's the XAML:
<GroupBox Header="Sub-Systems" Grid.Column="0" Grid.Row="0" Margin="5">
<Grid>
<Grid.Resources>
<DataTemplate x:Key="checkBox">
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsSelected}" />
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</Grid.Resources>
<ListBox ItemTemplate="{StaticResource checkBox}" ItemsSource="{Binding SubSystems}" />
</Grid>
</GroupBox>
Edit #2 -
Just to clarify, all of the examples populate the box, but none of the examples are breaking on the breakpoints in the setters.
I think that instead of a ListBox, you probably want an ItemsControl. ListBoxes assume that you want to select one of the SubSystem but really, you just want to arrange the items with data templates:
<ItemsControl ItemsSource="{Binding SubSystems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Checkbox IsChecked="{Binding IsSelected, Mode=TwoWay}" Content="{Binding Name}" />
</DataTemplate>
<ItemsControl.ItemTemplate>
</ItemsControl>
How about this:
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked={Binding IsSelected, Mode=TwoWay} /><TextBlock Text={Binding Name} />
</StackPanel>
</DataTemplate>
Do you mean something like this?
SubSystem class
public class SubSystem : INotifyPropertyChanged
{
private string mName;
private Boolean mIsSelected = false;
public SubSystem()
{
}
public SubSystem(string name, Boolean isSelected)
{
this.Name = name;
this.IsSelected = isSelected;
}
public string Name
{
get { return mName; }
set
{
if (mName != value)
{
mName = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
public Boolean IsSelected
{
get { return mIsSelected; }
set
{
if (mIsSelected != value)
{
mIsSelected = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("IsSelected"));
}
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
ViewModel
ObservableCollection<SubSystem> mSubSystems = new ObservableCollection<SubSystem>();
public ObservableCollection<SubSystem> SubSystems
{
get { return mSubSystems; }
set { mSubSystems = value; }
}
View
<ListBox x:Name="lstSubsystems" ItemsSource="{Binding SubSystems}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected}">
<ContentPresenter Content="{Binding Name}" />
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Hope that helps,
Wts
Modify the ListBox.ItemTemplate to use a checkbox, and bind the CheckBox.IsChecked to SubSystem.IsSelected and CheckBox.Content to SubSystem.Name:
XAML:
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelected}" Content="{Binding Name}" Margin="5" Focusable="False" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
C#:
private void window1_Loaded(object sender, RoutedEventArgs e)
{
this.SubSystems = new List<SubSystem>();
this.SubSystems.Add(new SubSystem() { Name = "SubSystem 1", IsSelected = false });
this.SubSystems.Add(new SubSystem() { Name = "SubSystem 2", IsSelected = false });
this.SubSystems.Add(new SubSystem() { Name = "SubSystem 3", IsSelected = true });
this.SubSystems.Add(new SubSystem() { Name = "SubSystem 4", IsSelected = false });
this.SubSystems.Add(new SubSystem() { Name = "SubSystem 5", IsSelected = true });
this.DataContext = this.SubSystems;
}
And make sure you set Focusable="False" to the CheckBoxes or else your users will be able to tab into them.
EDIT:
Also from what you added you might be missing the ElementName property (if SubSystems is NOT the DataContext of your window, you need to specify where the SubSystems property is coming from with the ElementName binding property):
<ListBox ItemTemplate="{StaticResource checkBox}" ItemsSource="{Binding ElementName=window1, Path=SubSystems}" />