WPF Tips
#1: Using BasedOn Style Property on DynamicResources
I've found that since you can't use BasedOn
on a DynamicResource
, you can „convert“ the DynamicResource
to StaticResource
by merging the ResourceDictionary
holding your „parent“ resources to your current Window/UserControl/whatever. This way you are now able to refer to the resource object (eg. Style) using StaticResource
. This way you can use Datatriggers
on DynamicResource
(through conversion).
Example:
<Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="/MyProject.Styles;component/ButtonStyles.xaml"/> </ResourceDictionary.MergedDictionaries> [*Your other resources can be put here*] </ResourceDictionary> </Window.Resources>
…
<Button Command="{Binding MyCommandInViewModel, RelativeSource={RelativeSource AncestorType=Window}}"> <Button.Style> <Style BasedOn="{StaticResource StyleFromButtonStyles}" TargetType="Button"> <Style.Triggers> <DataTrigger Binding="{Binding SomeBool}" Value="True"> <Setter Property="Button.Content" Value="{StaticResource SomeImage}"/> </DataTrigger> <DataTrigger Binding="{Binding SomeBool}" Value="False"> <Setter Property="Button.Content" Value="{StaticResource SomeOtherImage}"/> </DataTrigger> </Style.Triggers> </Style> </Button.Style> </Button>
Hence Datatriggers
are applied to a button styled in an imported ResourceDictionary
.
#2: How to fire a command on double-click listbox item?
The listbox itself is reacting to the double click, but only in the part of it's area that is not covered by a list box item.
You need the event handler to be tied to the listboxitem.
public class ControlItemDoubleClick : DependencyObject { public ControlItemDoubleClick() { } public static readonly DependencyProperty ItemsDoubleClickProperty = DependencyProperty.RegisterAttached("ItemsDoubleClick", typeof(bool), typeof(Binding)); public static void SetItemsDoubleClick(ItemsControl element, bool value) { element.SetValue(ItemsDoubleClickProperty, value); if (value) { element.PreviewMouseDoubleClick += new MouseButtonEventHandler(element_PreviewMouseDoubleClick); } } static void element_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) { ItemsControl control = sender as ItemsControl; foreach (InputBinding b in control.InputBindings) { if (!(b is MouseBinding)) { continue; } if (b.Gesture != null && b.Gesture is MouseGesture && ((MouseGesture)b.Gesture).MouseAction == MouseAction.LeftDoubleClick && b.Command.CanExecute(null)) { b.Command.Execute(null); e.Handled = true; } } } public static bool GetItemsDoubleClick(ItemsControl element) { return (bool)element.GetValue(ItemsDoubleClickProperty); }
<ListBox Name="SmallVideoPreviews" Grid.Column="1" MaxHeight="965" ItemsSource="{Binding BrowseVideos}" myStuff:ControlItemDoubleClick.ItemsDoubleClick="true" ItemTemplate="{StaticResource BrowseTemplate}"> <ListBox.InputBindings> <KeyBinding Key="p" Command="{Binding PlayVideoCommand}" CommandParameter="{Binding ElementName=SmallVideoPreviews, Path=SelectedItem}"/> <MouseBinding Gesture="LeftDoubleClick" Command="{Binding PlayVideoCommand}" CommandParameter="{Binding ElementName=SmallVideoPreviews, Path=SelectedItem}"/> </ListBox.InputBindings> </ListBox>
or
You can add a style to ListBox.ItemContainerStyle, and add an EventSetter there:
<ListBox> .... <ListBox.ItemContainerStyle> <Style TargetType="{x:Type ListBoxItem}" BasedOn="{StaticResource {x:Type ListBoxItem}}"> <EventSetter Event="MouseDoubleClick" Handler="ListBoxItem_MouseDoubleClick"/> </Style> </ListBox.ItemContainerStyle> </ListBox>
ListBoxItem_MouseDoubleClick is a method in your code behind with the correct signature for MouseDoubleClick.