Combobox ItemTemplate dont accept click - c#

I made a Usercontrol with a Combobox with itemTemplate. I set a an event trigger for click on Item. but its not work completely. it dosent accept the click. around the template or empty place before my text.
this is my code
<Combobox>
<Combobox.ItemTemplate>
<DataTemplate>
<Grid Height="25" FlowDirection="RightToLeft">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="25" />
<ColumnDefinition MinWidth="100" />
<ColumnDefinition Width="25" />
</Grid.ColumnDefinitions>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<command:EventToCommand Command="{Binding Command}"
CommandParameter="{Binding CommandParameter}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Image Height="20" Width="25" Grid.Column="0" VerticalAlignment="Center"
HorizontalAlignment="Center" />
<TextBlock Text="{Binding Title}" Grid.Column="1" VerticalAlignment="Center" />
<TextBlock Grid.Column="2" />
</Grid>
</DataTemplate>
</Combobox.ItemTemplate>
</Combobox>
it is a usercontrol that binds to a list of object contains Command and commandparameter, on click on each item one command should be raised.

Visual elements need to be assigned a brush in order for hit testing to take place.
(I did say IsHitTestVisibile so you wouldn't confuse the two).
You can do the following above your ItemTemplate in the Container that hosts it like so :
<ComboBox>
<ComboBox.ItemContainerStyle>
<Style TargetType="ComboBoxItem" BasedOn="{StaticResource {x:Type ComboBoxItem}}"> <!-- Or based on any other ComboboxItem style you have-->
<Setter Property="Background" Value="Transparent" />
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
FYI : IsHitTestVisibile is a flag stating that even if a Hit test did pass you can choose to disregard it.

What's wrong with SelectionChanged event of ListBox?
You could bind to that.
DataTemplate is for the data not for UI events. You use data-templates to tell WPF how you want to display data. At most you could have DataTriggers (which is again belong to data).
If you want to trap the click event on items, use ItemContainerStyle. The ItemContainerStyle is for styling the container of dataitem, which is ListBoxItem in this case.
Something of this sort might help:
<Style TargetType="ListBoxItem">
<Style.Triggers>
<EventTrigger RoutedEvent="Mouse.MouseEnter">
</EventTrigger>
</Style.Triggers>
</Style>

Related

Bind keypress event to ListViewItem in WPF

I have a ListView which populates the view with ListViewItems containing an image and text(file browser). How can I fire a Command when the user presses the 'Enter' key on a selected item while respecting the MVVM design pattern? I've searched and found a few solutions, but none of them seem to work for me.
<ListView ScrollViewer.HorizontalScrollBarVisibility="Hidden"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.ScrollUnit="Item"
Background="#fdfaf4"
Name="filesView"
ItemsSource="{Binding Items}">
<ListView.ItemTemplate>
<DataTemplate>
<!-- The image and item name -->
<Grid Width="{Binding ActualWidth, ElementName=filesView, Converter={x:Static converter:GridWidthToListViewWidthConverter.Instance}}"
Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.07*" MinWidth="25" MaxWidth="40" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Drive, file or folder -->
<Image Grid.Column="0"
Margin="0,0,5,0"
Name="itemType"
Source="{Binding Type,
Converter={x:Static converter:HeaderToImageConverter.Instance}}" />
<!-- The text is binded to the image size, so they'll expand/shrink together -->
<TextBlock Grid.Column="1"
VerticalAlignment="Center"
FontSize="{Binding ActualHeight,
ElementName=itemType, Converter={x:Static converter:ImageSizeToFontSizeConverter.Instance}}"
Text="{Binding Name}" />
<!-- The command to enter a drive/folder is called from here -->
<Grid.InputBindings>
<MouseBinding Gesture="LeftDoubleClick" Command="{Binding EnterCommand, Mode=TwoWay}" />
<KeyBinding Key="Enter" Command="{Binding EnterCommand, Mode=TwoWay}" />
</Grid.InputBindings>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The MouseBinding works just fine. I've tried putting the KeyBinding in the ListView instead of the grid and getting the focused item with the SelectedItem property but still nothing.
Implement the PreviewKeyDown event for the root Grid in the ItemTemplate or the ListViewItem container in the code-behind of the view and simply execute the command from there, e.g.:
private void ListViewItem_PreviewKeyDown(object sender, KeyEventArgs e)
{
var viewModel = DataContext as YourViewModel;
viewModel.YourCommand.Execute(null);
}
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<EventSetter Event="PreviewKeyDown" Handler="ListViewItem_PreviewKeyDown" />
</Style>
</ListView.ItemContainerStyle>
Or implement a behaviour that hooks up the event handler and does the same: https://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF.
Neither approach breaks the MVVM pattern since you are invoking the exact same view model command from the exact same view that the XAML markup is a part of.
MVVM is not about eliminating code from the views, it is about separation of concerns. If you invoke the command using a KeyBinding or an event handler doesn't matter.
Try Gesture="Enter";
<Grid.InputBindings>
<KeyBinding Gesture="Enter" Command="{Binding EnterCommand}" />
</Grid.InputBindings>

Cant get InputBinding to apply to entire ListBoxItem using DataTemplate WPF

Trying to get some keybindings onto my ListBoxItems in a ListBox in WPF. I am using MVVM, and binding the ItemSource of the ListBox to a list of ViewModels. This ViewModel has a string and a boolean for 'Selected'. I wish to display Selected as a property to a CheckBox.
I am trying to make it so that if I navigate the list items with the up and down arrows on the keyboard, and then press enter/space/whatever, I can toggle the Checkbox. However, I have to press tab first, to get focus to the StackPanel which contains the checkbox.
<DataTemplate x:Key="MyTemplate" DataType="{x:Type ViewModel}">
<Border Width="2" BorderBrush="Blue">
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyUp">
<i:InvokeCommandAction Command="{Binding EnterCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<CheckBox VerticalAlignment="Center"
Content="{Binding Name}"
IsChecked="{Binding Selected}"
Margin="3" />
</Border>
</DataTemplate>
=======================
<Popup x:Name="FilterPopup" Grid.Column="1"
IsOpen="{Binding IsChecked, ElementName=FilterButton}"
StaysOpen="False"
PlacementTarget="{Binding ElementName=FilterButton}"
Placement="Top">
<ListBox ItemsSource="{Binding ViewModels}"
ItemTemplate="{StaticResource MyTemplate}" />
</Popup>
Have I missed something obvious???
The triggers above are fired inside the data template, not inside item container. So if the last one is focused there is no effect.
To avoid this, the triggers should be specified on item container level:
<ListBox.ItemContainerStyle>
<Style>
<Setter Property="l:Attach.InputBindings">
<Setter.Value>
<InputBindingCollection>
<KeyBinding Command="{Binding EnterCommand}" Key="Enter" />
<KeyBinding Command="{Binding EnterCommand}" Key="Space" />
</InputBindingCollection>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
I've taken a way to set input bindings from style from this question.

StackPanel Collapsed and Visible on Button Click

I am trying to show one collapsed stackpanel on button click, but I'm having problems so I tried reverse my thoughts and I was able to collapse an visible stackpanel. But unfortunately I was unable to implement the behavior I want, show an collapsed stack panel on button click. To the code :D
XAML
<Button x:Name="sentButton" Content="Add Friend" Style="{DynamicResource FlatButtonStyle}" Margin="493,0,0,0" HorizontalAlignment="Left" Width="106"/>
<StackPanel Style="{DynamicResource stackCollapsed}" Visibility="Collapsed">
<Label Content="Invite Friends" FontWeight="Bold" Margin="0,0,477,0" Height="32" />
<StackPanel Orientation="Horizontal" Margin="26,0,0,0">
<Label Content="Enter your friend's email" Width="222" Height="25" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource MyTextBox}" x:Name="textBoxEmail" Width="298"/>
<Button x:Name="button1" Content="Send" Command="{Binding AddCommand}" Width="77" Style="{DynamicResource FlatButtonStyle}" Margin="20,0,0,0"/>
</StackPanel>
</StackPanel>
Styles
<!-- Style Collapsed-->
<Style x:Key="stackCollapsed" TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=sentButton,Path=IsPressed}" Value="true">
<Setter Property="StackPanel.Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
Instead of Button use ToggleButton and bind StackPanel.Visibility to ToggleButton.IsChecked property via BooleanToVisibilityConverter converter
<ToggleButton x:Name="sentButton" Content="Add Friend" Margin="493,0,0,0" HorizontalAlignment="Left" Width="106"/>
<StackPanel Visibility="{Binding ElementName=sentButton, Path=IsChecked, Converter={StaticResource BooleanToVisibilityConverter}}">
<Label Content="Invite Friends" FontWeight="Bold" Margin="0,0,477,0" Height="32" />
<StackPanel Orientation="Horizontal" Margin="26,0,0,0">
<Label Content="Enter your friend's email" Width="222" Height="25" />
<TextBox Text="{Binding Email, UpdateSourceTrigger=PropertyChanged}" x:Name="textBoxEmail" Width="298"/>
<Button x:Name="button1" Content="Send" Command="{Binding AddCommand}" Width="77" Margin="20,0,0,0"/>
</StackPanel>
</StackPanel>
where converter is defined as below
<Window.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</ResourceDictionary>
</Window.Resources>
The problem is the Visibility property in the <StackPanel> tab takes a higher precedence than anything set in a Style or Trigger, so the Trigger never gets applied. See the Dependency Property Precedence List for more details.
To fix your current solution, move the Visibliity property out of the <StackPanel> tag and into your Style, like this :
<Style x:Key="stackCollapsed" TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=sentButton,Path=IsPressed}" Value="true">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
<StackPanel Style="{DynamicResource stackCollapsed}">
...
</StackPanel>
That said, I would personally recommend something like a Toggle Button with the StackPanel.Visibility bound to the ToggleButton.IsChecked, like this answer suggests.
I solved set the Children to null
stackPanel.Children.Clear();
this work if you need to show / hide the panel the first time, it doesn't work if you need to do runtime
Simple as Stackpanel.Visibility = Visibility.Collapsed.

Passing DataContext in Telerik RadGridView

I use c# .NET 4.5 and WPF RadControls from Telerik.
On my MainWindow I have a RadTabControl and in my code behind I bind my MainViewModel like this:
this.DataContext = new MainViewmodel();
The ItemSource of the RadTabControl is bound in XAML:
<telerik:RadTabControl ... ItemsSourc={Binding Tabs} .. />
I also use a ContentSelector to load different Contents to my Tabs. These Contents are UserControls. On one UserControl I use a RadGRidView with it's own ItemsSource that I bind in the code behind:
TestGridView.ItemsSource = Tasks.GetTasks();
The RadGridView Columns bound to it's own style:
<telerik:RadGridView.Columns>
<telerik:GridViewDataColumn DataMemberBinding="{Binding ID}" Width="*" CellStyle="{StaticResource CellStyle}" />
</telerik:RadGridView.Columns>
<Style x:Key="CellStyle" TargetType="{x:Type telerik:GridViewCell}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border BorderBrush="#f2f2f2" BorderThickness="0,0,0,2" Padding="0,5,0,5">
<StackPanel Orientation="Horizontal">
<StackPanel Orientation="Vertical" Margin="10,0,0,0" VerticalAlignment="Top">
<TextBlock Text="{Binding Titel}" />
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Start}" Foreground="#9fa2ae"/>
<TextBlock Text=" XXX - XXX " />
<TextBlock Text="{Binding Startzeit}" Foreground="#9fa2ae" />
<telerik:RadButton Height="30" Content="Right Button" Command="{Binding AddTabCommand}" CommandParameter="Tab9999"/>
</StackPanel>
</StackPanel>
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The Problem is that the RadButton does not fire the DelegateCommand of my MainViewModel. I have also the same Button in the UserControl out of the RadGridView, this works fine.
Please can somebody tell me how I can fix this problem of my RadButton in the RadGridView?
Thanks a lot
Best Regards
RR
PS: I have a simple project, but can't attach it
The reason why this is happening is that the binding on your RadButton is trying to find the AddTabCommand on the DataContext of the button, not the parent Window.
To fix this, I would advise setting the style inside the Window's resources, and instead of using this:
Command="{Binding AddTabCommand}"
Give the Window a name, and use this:
Command="{Binding ElementName=windowName, Path=DataContext.AddTabCommand}"
Agree with what Mike said its not finding AddTabCommand in your DataContext(ViewModel).
You can try with specifying whole path of the command :
Command="{Binding ElementName=windowName, Path=NameSapce_Name.ViewModelName.AddTabCommand}".

WPF: ListItem does not receive focus when you press the button located on this ListItem

I have a ListBox with a DataTemplate. The template has a Button on it. Each item in the list shows the entity.
<ListBox Grid.Column="0"
x:Name="ThemesList"
ItemsSource="{Binding Themes}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
SelectedItem="{Binding SelectedTheme}"
ItemTemplate="{StaticResource ThemeListTemplate}"/>
<DataTemplate x:Key="ThemeListTemplate">
<Grid Grid.Column="1"
Grid.Row="0"
HorizontalAlignment="Right"
Margin="10">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Grid.Row="0"
HorizontalAlignment="Left"
Style="{StaticResource ElementButton}"
Command="{Binding Path=DataContext.ThemeEditorViewModel.OpenThemeEditorCommand, ElementName=ThemesBacklog}"
CommandParameter="{Binding Path=SelectedItem, ElementName=ThemesList}">
<TextBlock Text="Edit"/>
</Button>
<Button Grid.Row="1"
HorizontalAlignment="Left"
Style="{StaticResource ElementButton}"
Command="{Binding Path=DataContext.ThemeDeleteCommand, ElementName=ThemesBacklog}"
CommandParameter="{Binding Path=SelectedItem, ElementName=ThemesList}">
<TextBlock Text="Delete"/>
</Button>
</Grid>
</DataTemplate>
When you click on Button in the command is passed the property value SelectedItem. When you click on ListItem and then click Button - all fine. When I at once click on the Button - in the command is passed null. That is ListItem does not receive focus when you press the button located on this ListItem. How to solve this problem?
You could examine the IsKeyboardFocusWithin property on the ListBoxItems in a trigger, to find out whether a child (like your button), has focus, and set IsSelected to true if that is the case.
You do this by setting the ItemContainerStyle like this:
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Style.Triggers>
<Trigger Property="IsKeyboardFocusWithin" Value="True">
<Setter Property="IsSelected" Value="True" />
</Trigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>

Categories

Resources