How to bind CheckBox IsChecked to ListBox of CheckBoxes - c#

I have a list of check boxes and a single check box that acts as CheckAll/UncheckAll for all items in the listbox.
How can I make the chkAll Check Box checked if all the items are checked in the listbox binding ?
I could create a property in the view model to achieve that. I would like to do it in the xaml code.
<ListBox Name="listBox" ItemsSource="{Binding mySource}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsSelectedProperty}">
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<CheckBox Name="chkAll" Content="CheckAll/UnCheckAll" IsChecked ={}/>

I think you will need to have a higher-level view model property that reflects this additional state. The state has three possible values too, so be sure to set IsThreeState to true, and bind it to a Nullable<bool>.
Then in this property's setter, you can update all the other checkbox properties.
For each item's IsSelectedProperty, you'll need to update the three-state property too.

Related

ComboBox IsChecked Binding not working in Data Template

I have a ComboBox with a Textblock and a Checkbox displayed to allow me to set a view model boolean property based off the checkbox.
View Code
<ComboBox HorizontalAlignment="Left" IsEditable="True" IsReadOnly="True" Text="-- Filter Columns --">
<ComboBoxItem>
<ComboBoxItem.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Description"/>
<CheckBox IsChecked="{Binding DescriptionHeaderVisibility}"/>
</StackPanel>
</DataTemplate>
</ComboBoxItem.ContentTemplate>
</ComboBoxItem>
</ComboBox>
View Model Property
public bool DescriptionHeaderVisibility
{
get => _descriptionHeaderVisibility;
set => Set(ref _descriptionHeaderVisibility, value);
}
Useful information
I am using MVVM Light
If I do the exact same check box binding somewhere else on the page, it works and notifies my view model of the change.
Binding only does not work within the templated combo box
I am not sure why the binding is not working within the combo box template? Am I just missing something here that I don't know about? If I can get this binding to work properly the plan is to add another few rows of text blocks and check boxes all bound to different boolean properties in my view model.
Picture of drop down box
The problem is, you are using a ContentTemplate, but you do not give it any Content to display. If you just want to use the surrounding DataContext, you could write
<ComboBoxItem Content="{Binding .}">
Inspired by this answer to a similar question.

Disabling a TreeView item bound to an ItemsSource defined in xaml

I have a TreeView that I am binding to an ItemsSource that creates a CheckBox for each item. Here is the xaml:
<TreeView x:Name="ReasonTreeView" Height="Auto" Background="Transparent"
BorderThickness="0" IsTabStop="False"
ItemsSource="{Binding Path=AnswerOptions}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type QSB:Answer}" ItemsSource="{Binding Path=AnswerOptions}">
<StackPanel Orientation="Horizontal">
<CheckBox Margin="0,5"
IsChecked="{Binding Path=IsSelected}"
IsEnabled="{Binding Path=Value,
Converter={StaticResource ReasonValueToEnabledConverter}}"
Visibility="{Binding Path=AnswerOptions,
Converter={StaticResource ParentNodeVisConverter}}" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
In my application I then create multiple instances of these. Depending on the instance of the TreeView, certain CheckBoxes need to be disabled so the user can not select them, however I'm uncertain of how I can access the individual items in the HierarchicalDataTemplate in the code.
After looking around for a while the only thing I can think of is to build the whole TreeView in the code behind instead of the xaml, but I would rather not have to resort to that. Is there anything else that I can do?
To help clarify my point and for illustrative purposes, this is essentially what I want to be able to do (in pseudocode): ReasonTreeView.ItemsSource[5].IsEnabled = false;
Which would disable the CheckBox (and any other controls in that HierarchicalDataTemplateItem) at index 5 of the TreeView's ItemsSource
Let me know if more information is needed
I meant that binding on the checkbox's isenabled property Path=Value. That Value member has to be bool and implement INotifyPropertyChanged then you can control IsEnabled from your model. Dont forget to add Mode=Twoway to your binding
Instead of accessing the CheckBox through Control.ItemsSource property you should make the change in your underlying collection (that is itemssource of your control). After making the change notify the View (your Control) that data has been changed so update the control.
Implement INotifyPropertyChanged in your underlying class and after changing the Property (which is responsible for Enabled/Disabled) value Notify the View.
If you are not familiar with concepts of Data Binding and INotifyPropertyChanged, I would suggest you to read some basic tutorials about it. It is one of the major feature of WPF which makes life very easy for doing things like yours

selectedItem is not working in xaml

i am trying to set selected item through following code but its not working:
<StackPanel Orientation="Horizontal">
<TextBlock Text="Sort by" Margin="10" VerticalAlignment="Center"/>
<ComboBox Width="{StaticResource ComboWidth}" x:Name="sortcombo" ItemsSource="{Binding Path=SortOrder}" SelectionChanged="SearchCombo_SelectionChanged" SelectedItem="{Binding Path=DefaultSortIndex}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Sort}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
however it works fine if i use selectedIndex instead with binding to 0th index. Any thing wrong with declaration?
By the name of your property DefaultSortIndex maybe you are trying to bind an int for SelectedItem.
SeletedItem refers to an element of your collection binded to ItemsSource, so the property binded to SelectedItem must be of type of your collection elements.
If you bind int value to selected item then it will not work, you should bind element for that. For int value you can set it as mentioned in following post :
Set Selected Item of WPF Combobox to User Setting
found out the issue, actually the data source was creating new list everytime I call getData().

WPF combobox ItemTemplate does not apply

I have a combobox, which is bound to a dictionary of
<int, MyObject>
by the following code:
this.comboBox.ItemsSource= dictionary;
MyObject has some public properties, such as Name (string) and Selected (boolean).
In my Xaml I have an ItemTemplate on comboBox:
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Key, Mode=OneWay}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
When I run the app, I get the combobox filled with [1, MyObject] values.
What I eventually want to do is have a checkbox and a textblock in the ItemTemplate, which will be bound to MyObject.Selected and MyObject.Name. At the moment, I can't even get the datatemplate to display the dictionaty Key value.
Any ideas why the itemtemplate is being ignored? I've tried the full temeplate (stack planel containing a combobox and textblock), that showed the same values at runtime.
cheers.

Combobox not rendering in wpf datafrid

I have my data grid "dgSubsytem" column defined like below
<my:DataGridComboBoxColumn x:Name="cmbSubSysSupplier_SRV" Header="Supplier" Width="160"
ItemsSource="{Binding RelativeSource}" SelectedValueBinding="{Binding SupplierId}" />
As you see from the code i am having a combo box inside a grid .
Item source of this combo box is a datatable which is bound to it in the code behind .
Item source of the grid also another datatable bound in code behind .
code of binding item source of combobox in code behind is as follows
cmbSubSysSupplier_SRV.ItemsSource = dsComboBox.Tables[3].DefaultView;
cmbSubSysSupplier_SRV.DisplayMemberPath="FullName" ;
cmbSubSysSupplier_SRV.SelectedValuePath = "SupplierId";
Problem is combo box itself not rendering . But I can see the value of the Supplier rendered as text . What is the problem?
There are 2 parts here:
List of values to be populated in ComboBox: ItemsSource, should be bound using a StaticResource, with a List<X> fields exposed from your ViewModel.
The actual value (here X) should be bound to SelectedItemBinding using binding to data item.
No binding in code behind required.
At what point does your code-behind stuff run?
You're setting the ItemsSource in two places - in the XAML and in the Code-Behind. Whichever one runs second will overwrite the value of the first one, so only the last value set will be used.
I suspect your XAML is getting run last, and RelativeSource is probably not a property on your DataContext, so your ComboBox ends up being bound to nothing.
To fix it, simply remove your ItemsSource binding in the XAML for the DataGridComboBoxColumn
<my:DataGridComboBoxColumn x:Name="cmbSubSysSupplier_SRV"
Header="Supplier" Width="160"
SelectedValueBinding="{Binding SupplierId}" />
In addition, the DefaultView of a DataTable will return an object of type DataView, and DataView does not have properties called FullName or SupplierId, so your SelectedValuePath and DisplayMemberPath properties won't work.
I'd recommend building a list of KeyValuePair<int,string> out of your data items, and bind your ComboBoxColumn.ItemsSource to that list, then switch the SelectedValuePath to "Key" and the DisplayMemberPath to "Value"
I personally fought with DataGridComboBoxColumn for long time and i think the way is to use DataGridTemplateColumn. Here is an exemple :
Looks a lot of code but evective.
Put the collection as resource :
<Grid.Resources>
<CollectionViewSource x:Key="StructuresCollection" Source="{Binding StructuresList, Mode=OneTime}"/>
</Grid.Resources>
<DataGridTemplateColumn Header="Structure" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Structures.Name}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate >
<DataTemplate>
<ComboBox x:Name="CStructures" SelectedItem="{Binding Structures}" DisplayMemberPath="Name" SelectedValue="{Binding IDStructure, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="{Binding IDStructure}" ItemsSource="{Binding Source={StaticResource StructuresCollection}}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>

Categories