Set focus in WPF Checkbox list - c#

I have a WPF checkbox list containing car models. When I tab into the list the follwoing happens:
1) On first tab key press, the list item is selected
2) On second tab key press, the actual checkbox is selected allowing me to set the IsChecked state using the spacebar key.
Is it possible to automatically move the cursor to the checkbox when the list item is selected? (trying to avoid hitting tab twice)
XAML:
<ListBox ItemsSource="{Binding Cars}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Make}" IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Try adding this to your ListBox:
<ListBox.ItemContainerStyle>
<Style TargetType="Control">
<Setter Property="Focusable" Value="False" />
</Style>
</ListBox.ItemContainerStyle>

Tried Dan's solution, it works but it moves the focus out of the ListBox control after selecting the first checkbox, I was looking for something which prevents the focus from being set to the selected listbox item while still allowing to tab through all the checkboxes in the list.
The following link helped me - Keyboard focus to list box items in WPF
I've made a few changes to have create border as well as the verticall scrollbar, complete XAML below:
<Border BorderThickness="0.8" BorderBrush="Gray">
<ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto" Margin="1">
<ItemsControl ItemsSource="{Binding Cars}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Make}" IsChecked="{Binding IsChecked,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Border>

Related

Selecting null item in a ListBox

I have a ListBox with an ItemsSource that can contain null values.
I can't select those null values in the ListBox with the mouse, but I can with the keyboard.
Is there any way to make null items selectable by mouse?
Example xaml:
<ListBox>
<ListBox.Items>
<x:Null />
<system:String>Hello</system:String>
<x:Null />
</ListBox.Items>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text">
<Setter.Value>
<Binding />
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=.}" Value="{x:Null}">
<Setter Property="Text" Value="Null value!" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Which results in:
however, I can't select any of the Null value! entries using the mouse, which is what I want to do.
If it can be done with another pure-xaml solution, that'd be fine. I'd prefer to not have to use any converters, if possible.
I'm afraid you will have to go for converters (don't really know why you don't want some ?)
From this SO question :
The null "item" is not being selected by the keyboard at all - rather
the previous item is being unselected and no subsequent item is (able
to be) selected.
In short, you can neither select nor deselect a null item in a
ComboBox. When you think you are doing so, you are rather deselecting
or selecting the previous or a new item.
This can perhaps best be seen by adding a background to the items in
the ComboBox. You will notice the colored background in the ComboBox
when you select "Hello", but when you deselect it via the keyboard,
the background color disappears. We know this is not the null item,
because the null item actually has the background color when we drop
the list down via the mouse!
The following XAML, modified from that in the original question, will
put a LightBlue background behind the items so you can see this
behavior.
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
<ComboBox x:Name="bars" Height="21" SelectedItem="{Binding Bar}">
<ComboBox.ItemTemplate>
<DataTemplate>
<Grid Background="LightBlue" Width="200" Height="20">
<TextBlock Text="{Binding Name}" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel> </Window> ```
If you want further validation, you can handle the SelectionChanged event on the ComboBox and see that
"selecting the null item" actually gives an empty array of AddedItems
in its SelectionChangedEventArgs, and "deselecting the null item by
selecting 'Hello' with the mouse" gives an empty array of
RemovedItems.

ListBox checklist SelectedItem returns null

I want to create a Listbox from where it's possible to select elements with checkboxes. It gets the elements through data-binding from a database. The items appear in the Listbox, but when I send the form, the code-behind doesn't receive a SelectedItem value.
The XAML section for the listbox looks like this:
<Grid x:Name="grMozik" Visibility="Visible" Margin="0,0,0,0" DataContext="{Binding}" Grid.Row="3" Grid.ColumnSpan="2">
<ListBox Name="lbMozik" Margin="15" Width="300" Height="200" ItemsSource="{Binding}">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Focusable" Value="False"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding MoziNeve}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
And for test purposes the code that would show the selected item looks like this:
string text = ((ListBoxItem)lbMozik.SelectedItem).Content.ToString();
MessageBox.Show(text2);
ListBox.SelectedItem comes from a ListBoxItem which has IsSelected property set to true. If you want to select by CheckBoxes, then bind each of them to owner ListBoxItem.IsSelected:
<CheckBox Content="{Binding MoziNeve}"
IsChecked="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListBoxItem}}"/>

How do I get rid of unwanted padding in a Listview row

I am trying to figure out how to get rid of the padding below the text in a listview row:
And my markup for the Listview:
<ListView
ItemsSource ="{Binding AllowedApplicants}"
Height="250"
Width="219"
VerticalAlignment="Top"
Grid.Row="3"
Grid.Column="1"
Grid.ColumnSpan="2"
Margin="20,5"
BorderBrush="Bisque"
BorderThickness="2">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Padding="5,5" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I can't figure out where this extra padding (red arrow) is coming from. The properties for the row's padding and margins defaults to zero all around. I added the five to keep the text off the borders. The list view row seems to have a default Height which cannot be adjusted.
Try adding
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="MinHeight" Value="0"/>
</Style>
</ListView.ItemContainerStyle>
to your List View or use Live Property Explorer and Live Visual Tree Viewer from Visual Studio and peek into the ListViewItem.

Hide checkbox, but show its content

Is it possible to hide a checkbox, but leave its content visible?
<ListBox
ItemsSource ="{Binding MyItemCollection}"
SelectionMode="Single"
Width="300"
Height="320">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}">
<CheckBox.Content>
<TextBlock Text="{Binding Item.Code}"/>
</CheckBox.Content>
</CheckBox>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel>
<CheckBox Content="Edit Mode"
IsChecked="{Binding Path=EditModeSelected, Mode=TwoWay}">
</CheckBox>
</StackPanel>
I would like to hide the checkboxes in the list box when I turn Edit Mode off (so it should be binded to EditModeSelected), but the text should be left visible.
In order to do so You can keep two TextBlocks. In edit mode visible CheckBox and hide TextBlock and in reader mode vice versa. I hope this may help. As DataTemplate can have only one child here's the fix
Create a Window Resource like below. Two Data Templates were created one for edit mode and another for Reader Mode.
<Window.Resources>
<DataTemplate x:Key="EditModeTemplate">
<CheckBox IsChecked="{Binding IsChecked}">
<CheckBox.Content>
<TextBlock Text="{Binding Item.Code}"/>
</CheckBox.Content>
</CheckBox>
</DataTemplate>
<DataTemplate x:Key="ReaderModeTemplate">
<TextBlock Text="{Binding Item.Code}"/>
</DataTemplate>
</Window.Resources>
Now in .cs file assign the Date Template as per requirements.
if (EditMode)
{
DemoCollection.ItemTemplate = this.Resources["EditModeTemplate"] as DataTemplate;
}
else
{
DemoCollection.ItemTemplate = this.Resources["ReaderModeTemplate"] as DataTemplate;
}
3 possible solutions come in my mind - two of them more or less "hacks" and one more or less clean solution:
A checkbox and textblock for every item - you can get problems with margins etc
A checkbox with no content (which is only visible when in edit mode), and a textblock which is always visible
Take the default controltemplate for checkbox (Default ControlTemplate for CheckBox) and bind the visibility of the checkbox
Here is a Xaml only solution pulled from a project I am working on. In this case "ShowCheck" is a field in the current binding context saying whether or not to show the check.
<CheckBox Content="{Binding Name}">
<CheckBox.Style>
<Style TargetType="CheckBox">
<Style.Triggers>
<DataTrigger Binding="{Binding ShowCheck}" Value="False">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<ContentControl Content="{TemplateBinding Content}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</CheckBox.Style>
</CheckBox>
Basically if the checkbox should be invisible, then I use a style and a trigger to change the checkbox's template to something without the checkbox. My implementation the content is just a string, so this works. If you were putting more complicated objects into the checkbox, you might need to shuttle the ContentTemplate, ContentTemplateSelector, and related fields into the ContentControl that is used to replace the checkbox

How to make the entire item area of multi-select combobox clickable

I have a multi-select combobox with the below datatemplate
<DataTemplate>
<CheckBox HorizontalAlignment="Stretch" HorizontalContentAlignment="Stretch"Content="{BindingTitle}"
IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"
Click="CheckBox_Click"/>
</DataTemplate
When I click on the checkbox or checkbox text the item in the combobox gets selected , but when click outside the check-box area, I expect it to be combobox item to be selected but to my surprise it is not getting selected.Is it a bug or this the expected behaviour.
Any help on how to make the entire area clickable.
add this to your combobox:
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</ComboBox.ItemContainerStyle>
the item container is responsible for the click outside the item and the value is NOT stretch by default so this should sort it out, maybe some margin on the sides , depends on the style
You have set the HorizontalContentAlignment property to True on the wrong element... you should set it to True on the collection control instead, as it:
Gets or sets the horizontal alignment of the control's content.
<ListBox ItemsSource="{Binding SomeCollection}" HorizontalContentAlignment="Stretch" />
UPDATE >>>
This does work and if it doesn't for you, it's because you must have some other XAML elements getting in the way. Try this really simple example in a new project:
<DataTemplate DataType="{x:Type System:Boolean}">
<CheckBox Content="Hello" IsChecked="{Binding ., Mode=TwoWay}" />
</DataTemplate>
...
<ListBox ItemsSource="{Binding SomeCollection}" HorizontalContentAlignment="Stretch" />
...
SomeCollection = new ObservableCollection<bool>();
SomeCollection.AddRange(new bool[] { true, false, true, true, false };

Categories

Resources