I use this article to create multi-select ComboBox.
I want to select/unselect the CheckBox inside each item when pressing the Space button.
I tried to add PreviewKeyDown for the CheckBox but the event doesn't get raised.
I also tried adding PreviewKeyDown in the StackPanel but then I can't get the selected item that it's CheckBox is currently checked.
You need to handle KeyUp of the combobox and make sure that the dropdown is open.
Update:
<Grid>
<ComboBox x:Name="cbo" KeyUp="ComboBox_KeyUp" Height="30" Width="200">
<CheckBox Content="checkbox1"/>
<CheckBox Content="checkbox2"/>
<CheckBox Content="checkbox3"/>
<CheckBox Content="checkbox4"/>
<CheckBox Content="checkbox5"/>
</ComboBox>
</Grid>
///////////////////////////
private void ComboBox_KeyUp(object sender, KeyEventArgs e)
{
if (cbo.IsDropDownOpen)
{
// select first and second
(cbo.Items[0] as CheckBox).IsChecked = true;
(cbo.Items[1] as CheckBox).IsChecked = true;
}
}
I use EventSetter.
<ComboBox.Resources>
<Style TargetType="{x:Type ComboBoxItem}">
<EventSetter Event="PreviewKeyDown" Handler="EventSetter_OnHandler" />
</Style>
</ComboBox.Resources>
and in code behind.
private void EventSetter_OnHandler(object sender,KeyEventArgs e)
{
var item=((ComboBoxItem)sender).DataContext as Node;
item.IsSelected=!item.IsSelected;
}
Related
I have a ListBox with SelectionMode="Extended". You can only deselect the last item by holding down ctrl while clicking on it. I would like to be able to deselect the item by just clicking on it while not changing the behavior of the Extended selection mode other than that.
I only found one question about this topic and it actually has a different goal (being able to deselect all items by clicking outside of the ListBox).
If I understand your requirement correctly you could handle the PreviewMouseLeftButtonDown event for the ListBoxItem container and de-select it if it's already selected:
<ListBox SelectionMode="Extended">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="OnMouseLeftButtonDown"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBoxItem>1</ListBoxItem>
<ListBoxItem>2</ListBoxItem>
<ListBoxItem>3</ListBoxItem>
</ListBox>
private void OnMouseLeftButtonDown(object sender, MouseEventArgs e)
{
ListBoxItem lbi = sender as ListBoxItem;
if (lbi != null)
{
if (lbi.IsSelected)
{
lbi.IsSelected = false;
e.Handled = true;
}
}
}
This should allow you to be able to de-select an item without using the CTRL key.
I want to delete my listbox item on right click. But, right click event not worked in my case.
Below is the code which I tried.
In constructor:
listBox1.MouseDown += new MouseButtonEventHandler(listBox1_MouseRightClick);
Right Click:
private void listBox1_MouseRightClick(object sender, MouseButtonEventArgs e)
{
if (sender is ListBoxItem)
{
ListBoxItem item = (ListBoxItem)sender;
Harvest_TimeSheetEntry entryToDelete = (Harvest_TimeSheetEntry)item.DataContext;
MessageBoxResult Result = System.Windows.MessageBox.Show("Are you sure?", "Delete Confirmation", System.Windows.MessageBoxButton.YesNo);
if (Result == MessageBoxResult.Yes)
{
Globals._globalController.harvestManager.deleteHarvestEntry(entryToDelete);
}
else
{
System.Windows.MessageBox.Show("Delete operation Terminated");
}
}
}
In xaml:
<ListBox x:Name="listBox1" ItemsSource="{Binding}" Margin="0,131,0,59" ItemTemplateSelector="{StaticResource templateSelector}" SelectionMode="Single" MouseRightButtonDown="listBox1_MouseRightClick">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="MouseDown" Handler="listBox1_MouseRightClick"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
Please suggest, how should I use right click event so it could work?
Your original code seems redundant and verbose. MouseRightButtonDown isn't working because there is already an event handling listbox item selection and the ListBoxItem datacontext is simply the SelectedItem of listBox1.
Get rid of overriding the style and just declare the listbox with the preview event. This will tunnel MouseRightButtonDown instead of bubble it.
<ListBox x:Name="listBox1"
ItemsSource="{Binding}"
ItemTemplateSelector="{StaticResource templateSelector}"
Margin="0,131,0,59"
SelectionMode="Single"
PreviewMouseRightButtonDown="listBox1_MouseRightClick" />
In the constructor, get rid of this
listBox1.MouseDown += new MouseButtonEventHandler(listBox1_MouseRightClick);
Now in the event handler, sender is your listbox1 but if you're not tying this event to other listboxes, simply get the selectedItem from listbox1 and cast it to the appropriate object. Otherwise if you decide you want the functionality on multiple listboxes cast sender to ListBox
private void listBox1_MouseRightClick(object sender, MouseButtonEventArgs e)
{
Harvest_TimeSheetEntry entryToDelete = (Harvest_TimeSheetEntry)listBox1.SelectedItem;
if(entryToDelete != null)
{
//Do work
}
}
Deleting records on right click is not a good design and it leads users make more confuse the functionality. Still if you want to do something, then you can go for the PreviewMouseRightButtonDown event. Please see the below snippet
ListBox1.PreviewMouseRightButtonDown += new MouseButtonEventHandler(ListBox1_MouseRightButtonDown);
Change your XAML as follows
<ListBox x:Name="listBox1"
ItemsSource="{Binding}"
Margin="0,131,0,59"
ItemTemplateSelector="{StaticResource templateSelector}"
SelectionMode="Single">
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<EventSetter Event="PreviewMouseRightButtonDown"
Handler="ListBox1_PreviewMouseRightButtonDown" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
I am building a windows store app and due to UI problems I have to implement checkbox inside combobox.I am stucked at following problem:I want to display the checked Item in "Combobox with Checkbox" .
What I want to do :
http://blogs.microsoft.co.il/blogs/justguy/image_2827F1EB.png
<ComboBox x:Name="cb2"
DropDownOpened="cb2_DropDownOpened_1"
DropDownClosed="cb2_DropDownClosed_1"
SelectionChanged="cb2_SelectionChanged_1"
Width="310"
ItemsSource="{Binding Members}"
DisplayMemberPath="{Binding Name}"
Height="50" BorderBrush="#FF0A2562"
Tag="{Binding index}"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox
Background="Black"
BorderBrush="Black"
Tag="{RelativeSource TemplatedParent}"
Content="{Binding Name}"
IsChecked="{Binding Path=IsSelected,Mode=OneWay}"
Unchecked="CheckBox_Unchecked_1"
Click="CheckBox_Click"
/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Code Behind:
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
CheckBox chk = (CheckBox)sender;
string k =(string) chk.Content;
chkstr.Add(k);
}
private void CheckBox_Unchecked_1(object sender, RoutedEventArgs e)
{
CheckBox chk = (CheckBox)sender;
string k = (string)chk.Content;
chkstr.Remove(k);
// vl.selectedmembers.Remove(key);
}
In ComboBox Standard Template defined by Microsoft add a TextBlock in ContentPresenter.
Bind the Text Property of TextBlock with string.Now you can add the checked Items to string by converting the items to string explicitly.
#Patrick : ItemTemplate and ItemContainerStyle both will work.
You need to retemplate the ComboBoxItem. Specify ComboBox.ItemContainerStyle instead of ComboBox.ItemTemplate. Inside of ComboBox.ItemContainerStyle, have a setter for Template. Copy the default template and add a CheckBox. Template-bind CheckBox.IsChecked to IsSelected, or animate IsChecked to true using an object animation in the Selected visual state.
Your approach won't work since IsSelected is a property on the ComboBoxItem container, not the data context.
I have a WPF TreeView with XAML shown below:
<TreeView x:Name="twElements">
<TreeView.Resources>
<v8r:IconTypeConverter x:Key="IconConverter"/>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<EventSetter Event="MouseDoubleClick" Handler="twElements_MouseDoubleClick" />
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ChildItems}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Icon, Converter={StaticResource IconConverter}}"/>
<TextBlock Text="{Binding Text}" Margin="3,0,0,0"/>
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
The task is to open some form after double click on a child item.
code-behind for DoubleClick event:
private void twElements_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (e.Source is TreeViewItem && ((TreeViewItem)e.Source).IsSelected)
{
e.Handled = true;
var twi = (TreeViewItem)e.Source;
var Editable = twi.Header as IEditable;
if (Editable != null)
{
Window Editor = Editable.GetEditor();
Editor.Show(); // Editor is a WPF.Window
}
}
}
The problem: After desired window is opened, form with a treeview activates itself, making new window to go background.
How to make new window to remain active?
You probably need to let WPF finish the job of handling the current mouse click event(s) before you open the new Window. Let the new window be the next UI job by adding it to the current Dispatcher's queue like this:
(...)
//Editor.Show();
Action showAction = () => Editor.Show();
this.Dispatcher.BeginInvoke(showAction);
in constructor of new form set
this.Focus();
Also, does your new form should be Modal window? if yes use Editor.ShowDialog() instead of Editor.Show(); It will automatically solve issue with focus
Is there a way to make the selectionchanged event fire every time a selection in the listview is clicked, instead of only when it changes?
For example, lets say i have a listview with only one object in it. The user clicks that object, and that object contains information that populates some textboxes below. The user starts changing some of the values in these textboxes (which are not bound to the object). They then decide that they dont want what is in those text boxes so they'd like to reset everything to what is in the object in the listview. But when they click the one object in the listview, nothing happens, because the selection has not changed.
Hope that makes sense. Anyone know how I can get around this?
The ListView.SelectionChanged and ListViewItem.Selected events are not going to re-fire if the item is already selected. If you need to re-fire it, you could 'deselect' the item when the event fires.
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
foreach (var item in e.AddedItems.OfType<ListViewItem>())
{
Trace.WriteLine("ListViewItem Selected");
item.IsSelected = false;
}
}
Thus allowing you to re-select it ad nauseum. However, if you don't need the actual selection then you should be using an ItemsControl.
If you do want to maintain the select-ability of the item(s) then you should look at registering to a different event than ListView.SelectionChanged, or ListView.Selected. One that works well for this is PreviewMouseDown, as like the initial item selection we want it to occur on both left and right clicks. We could attach it to the single ListViewItem, but since the list may at some point gain more items, we can assign it to all items by using the ItemContainerStyle property of the ListView.
<ListView SelectionChanged="ListView_SelectionChanged">
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<EventSetter Event="PreviewMouseDown"
Handler="ListViewItem_PreviewMouseDown" />
</Style>
</ListView.ItemContainerStyle>
<ListViewItem>Item 1</ListViewItem>
<ListViewItem>Item 2</ListViewItem>
<ListViewItem>Item 3</ListViewItem>
<ListViewItem>Item 4</ListViewItem>
</ListView>
private void ListViewItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Trace.WriteLine("ListViewItem Clicked: " + (sender as ListViewItem).Content);
}
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(ListView.SelectedIndex != -1)
{
//to do staff
}
ListView.SelectedIndex = -1;
}
also we can use this one!
<ListView x:Name="ListView"
Height="Auto" SelectionChanged="ListView_OnSelectionChanged"
Width="260"
Margin="0,-12,0,-25">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding name_to_show_menu,Mode=TwoWay}" Tapped="UIElement_OnTapped"></TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and in code behind
private void UIElement_OnTapped(object sender, TappedRoutedEventArgs e)
{
//this fire every time
}