WPF Design Time Data in Menu Subitem Style - wpf

I have a WPF project with a menu. One of the menus has subitems dynamically generated by binding to a collection in code behind. Here is the XAML for this item:
<MenuItem Header="Open Files" Name="MiInsertOpen"
d:DataContext="{d:DesignInstance Type={x:Type core:DBInterface}}"
ItemsSource="{Binding InsertableDBs}">
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding DisplayName}" />
<Setter Property="ToolTip" Value="{Binding FilePath}" />
<Setter Property="Command" Value="{Binding DataContext.CmdInsert,
RelativeSource={RelativeSource FindAncestor,
AncestorType=MenuItem, AncestorLevel=2}}" />
<Setter Property="CommandParameter" Value="{Binding FilePath}" />
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
This all works fine at run time and I get what I would expect, etc. The data context of each subitem is the proper DB that it represents.
At design time, however, the parent MenuItem has it's design time data context properly set and recognizes 'IsertableDBs', but in the style it's complaining that it can't find 'DisplayName' and the other properties on type 'DBInterface' (the DataContext type for the parent menu). How do I tell it that the items in that style should have DataContext of the DB type?

Ok after googling some more I found the answer here. This seems to be working; the only thing I have to add is that the d: tag comes up empty in Intellisense when entering it; just type in 'Style.DataContext' manually and it works...

Related

Why does only part of the context menu trigger the associated command in WPF?

I have a need to bind context menu items to a list in my view model. It works and the code is rather simple, but there is one problem that my users won't accept. You have to click in a certain area of the context menu in order to get the command to trigger.
If you click outside of the darker blue area then the command does not trigger.
The XAML is as follows:
<ContextMenu ItemsSource="{Binding MyContextMenuItems}">
<ContextMenu.ItemTemplate>
<DataTemplate>
<MenuItem Header="{Binding Header}" Command="{Binding Command}" />
</DataTemplate>
</ContextMenu.ItemTemplate>
</ContextMenu>
It appears that the dark blue is the actual MenuItem control, but I need the parent to be the clickable area, I would also prefer that it was all highlighted the same, but I think That that won't be very difficult to figure out once I know the solution to the main issue.
Thanks to DRapp's comment I figured out the solution to my issue. The menu item is actually created automatically and I was creating an menu item inside of the one that was created for me. The solution was to define the ContextMenu.ItemContainerStyle instead of using the ContextMenu.ItemTemplate. Below is the final XMAL.
<ContextMenu ItemsSource="{Binding MyContextMenuItems}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}">
<Setter Property="Header" Value="{Binding Header}" />
<Setter Property="Command" Value="{Binding Command}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>

Change context menu in xaml

I've got a view with two large context menus defined as resouces. They look something like this (only larger) :
<ContextMenu x:Key="ContextMenu1">
<MenuItem Header="Append" Command="{Binding AppendCommand}" />
<MenuItem Header="Edit" Command="{Binding AppendCommand}" />
</ContextMenu>
<ContextMenu x:Key="ContextMenu2">
<MenuItem Header="Delete" Command="{Binding DeleteCommand}" />
<MenuItem Header="Verify" Command="{Binding VerifyCommand}" />
</ContextMenu>
I know that I can dynamically show / hide items with the canExecute method of the command. But since this is two completely different modes I would like to just Bind to a bool property that decides which context menu to display. Something like this:
<ListView ContextMenu={binding ContextMenuSelector}>
Does anyone know how I can do something like that ?
Consider using a DataTemplateSelector.
The DataTemplateSelector enables you to display specific presentations based on the context of each datacontext item within your itemscontrol.
I have used it for context menu items that may differin behavior.
I got a few good ideas from the DataTemplateSelector, but I ended up with a style with data trigger:
<Style TargetType="{x:Type StackPanel}" x:Key="stackPanelStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=AppendMode}" Value="True">
<Setter Property="ContextMenu" Value="{DynamicResource PanelContextMenuAttachFile}"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding Path=AppendMode}" Value="False">
<Setter Property="ContextMenu" Value="{DynamicResource PanelContextMenu}"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>

mvvm with prism: setting view from menu item

I am new to wpf world. I have a context menu in the shell as below:
<ContextMenu>
<MenuItem Header="Login"
Command="{Binding WorkSpaceViewSetter}" CommandParameter="DemoApplication.View.LoginView">
<MenuItem.Icon>
<Image Height="16" Width="16" Stretch="Uniform" Source="/Images/login.png"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Modules" ItemsSource="{Binding AppModules}">
<MenuItem.Icon>
<Image Source="/Images/modules.png"/>
</MenuItem.Icon>
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding ModuleName}"/>
<Setter Property="Command" Value="{Binding ElementName=win, Path=DataContext.WorkSpaceViewFromType}"/>
<Setter Property="CommandParameter" Value="{Binding MainViewType}"/>
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
</ContextMenu>
Each element in the itemssource AppModules of the Modules menuitem has a property named MainViewType of type System.Type. I want to change the view of a region when a menuitem gets clicked and am thinking of using a single ICommad in the shellviewmodel and passing the MainViewType as command parameter. However, the above code is not working.
I was wondering why then the Modules menuitem gets populated from the itemssource as expected.
I have noticed that the command binding on the Login menuitem is also not working even though it should have, since the itemssource property of Modules gets properly bounded. Can anybody please suggest how to make it work?
Context menus aren't on the same visual tree as the rest of your window, so using ElementName in the binding won't work. You'll need to using PlacementTarget instead. Without knowing how your viewmodels are structured it's difficult to give a definitive answer but your solution will look something like:
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding ModuleName}"/>
<Setter Property="Command" Value="{Binding PlacementTarget.DataContext.WorkSpaceViewFromType}"/>
<Setter Property="CommandParameter" Value="{Binding MainViewType}"/>
</Style>
</MenuItem.ItemContainerStyle>

MenuItem and IcollectionView

I want to display a list of available languages in a menu.
The languages are available as an ICollectionView.
This is the code:
<Menu DockPanel.Dock="Top">
<Menu.Resources>
<Style x:Key="LanguageMenuStyle" TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Name}"></Setter>
<Setter Property="IsCheckable" Value="True"/>
</Style>
</Menu.Resources>
<MenuItem Header="Language" ItemsSource="{Binding Languages}"
ItemContainerStyle="{StaticResource LanguageMenuStyle}">
</MenuItem>
</Menu>
Languages is an ICollectionView created as default view from a list of cultures.
The menu is displayed correctly.
Now I would like to bind to the CurrentChanged event when the selection in the menu changes, but since there is no IsSynchronizedWithCurrentItem property, how could I do that?
And is there a way to allow only one item to be checked at a time?

WPF RibbonButton: LargeImageSource and Label not updated via DataTriggers

I'm puzzled by a peculiar phenomenon in RibbonButton's behavior.
Everything works fine when I set the LargeImageSource and the Label statically in XAML:
<ribbon:RibbonButton x:Name="ButtonArchive"
LargeImageSource="..\Assets\archive_insert.png"
Label="{Binding Path=ItemArchiveButton,
Source={StaticResource Strings}}"/>
But when I try to modify these properties via DataTriggers - nothing seems to be happening.
The triggers do work; I can see the other properties - like Command or IsEnabled - set OK in the same trigger. It's just these too...
Here's the XAML:
<ribbon:RibbonButton x:Name="ButtonArchive"
LargeImageSource="..\Assets\archive_insert.png"
Label="{Binding Path=ItemArchiveButton, Source={StaticResource Strings}}">
<ribbon:RibbonButton.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding ="{Binding ElementName=ItemsList, Path=SelectedItem.IsArchived}" Value="false">
<Setter Property="ribbon:RibbonButton.Command" Value="{Binding ArchiveItemCommand}" />
<Setter Property="ribbon:RibbonButton.LargeImageSource" Value="..\Assets\archive_insert.png" />
<Setter Property="ribbon:RibbonButton.Label" Value="{Binding Path=ItemArchiveButton, Source={StaticResource Strings}}" />
</DataTrigger>
<DataTrigger Binding ="{Binding ElementName=ItemsList, Path=SelectedItem.IsArchived}" Value="true">
<Setter Property="ribbon:RibbonButton.Command" Value="{Binding RestoreItemCommand}" />
<Setter Property="ribbon:RibbonButton.LargeImageSource" Value="..\Assets\archive_extract.png" />
<Setter Property="ribbon:RibbonButton.Label" Value="{Binding Path=ItemRestoreButton, Source={StaticResource Strings}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</ribbon:RibbonButton.Style>
</ribbon:RibbonButton>
Setting the Command works fine in the both conditions, but not the other 2 properties...
Any advice will be welcome.
I asked the same question at the MSDN forum, and the answer I've got really solved this.
The problem is your setting properties for LargeImageSource and Label in the button itself. When you do this it takes precidence over your style triggers. I suggest using setters in the style to set your defaults, and remove the property settings it the button.

Resources