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>
Related
I cannot figure out how to do this, and one would think it would be pretty simple.
I have a MenuItem that's part of a ContextMenu. I have a binding to a boolean property on a viewmodel. Depending on the state of this property, I want the MenuItem's header text and icon to change.
I could certainly use an IValueConverter for this, but I'm sure that there is a more elegant solution using a DataTemplate and triggers. I just can't figure out the proper markup.
The code I worked up (snipped below) has two problems: one the HeaderTemplate doesn't appear to contain the icon, so what would be the MenuItems's text contains the icon as well (normally the icon appears on in left hand section - see image and compare with the Copy and Clear menuitems). Additionally, clicking the MenuItem doesn't trigger the DataTemplate changes (note the command works, the viewmodel binding does in fact toggle the true/false state).
<ContextMenu>
<MenuItem Command="{Binding Source={x:Static cmd:Commands.PauseCommand}}"
CommandParameter="{Binding}">
<MenuItem.HeaderTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image x:Name="img" Source="../Icons/pause.png"/>
<TextBlock x:Name="txt" Text="Pause"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding IsPaused}" Value="True" >
<Setter Property="Image.Source" Value="../Icons/play.png" TargetName="img"/>
<Setter Property="Text" Value="Play" TargetName="txt"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</MenuItem.HeaderTemplate>
</MenuItem>
You mean like this? Dont make things harder than they are ;)
<ContextMenu>
<MenuItem Command="{Binding Source={x:Static cmd:Commands.PauseCommand}}"
CommandParameter="{Binding}">
<MenuItem.Style>
<Style TargetType="MenuItem">
<Setter Property="Icon" Value="../Icons/play.png>"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding IsPaused, Mode=OneWay}" Value="True">
<Setter Property="Icon" Value="../Icons/pause.png"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.Style>
</MenuItem>
</ContextMenu>
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>
I know there is a way to block or now show context menu by using ContextMenuOpening event.
But I still want to show the context menu, just disable everything in it, is there a way to do it?
How can I disable all the menu item at a same time?
<DataTemplate x:Key="ItemDataTemplate">
<Grid Background="Transparent">
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="New" Click="New_Click" />
<Separator />
<MenuItem Header="Duplicate" Click="Duplicate_Click"/>
<MenuItem Header="Delete" Click="Delete_Click" />
<MenuItem Header="Rename" Click="Rename_Click" />
<Separator />
<MenuItem Header="Export..." Click="Export_Click" />
<MenuItem Header="Print..."
Command="ApplicationCommands.Print"
InputGestureText="" />
<Separator />
<MenuItem Header="Properties" Click="Properties_Click" />
</ContextMenu>
</Grid.ContextMenu>
<StackPanel Orientation="Horizontal"
Margin="0,0,10,0"
HorizontalAlignment="Stretch"
Background="Transparent"
IsHitTestVisible="False">
</StackPanel>
</Grid>
</DataTemplate>
<Style x:Key="z3r0_Style_TextBox_Default" BasedOn="{x:Null}"
TargetType="{x:Type TextBox}">
<Setter Property="FontSize" Value="11"/>
<Setter Property="Background" Value="{StaticResource z3r0_SolidColorBrush_DarkerGray}"/>
<Setter Property="BorderBrush" Value="{x:Null}"/>
<Setter Property="FontFamily" Value="Consolas"/>
<Setter Property="Foreground" Value="{StaticResource z3r0_SolidColorBrush_Green}"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="MinWidth" Value="10"/>
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu IsEnabled="False" Visibility="Hidden">
</ContextMenu>
</Setter.Value>
</Setter>
For me, setting IsEnabled to False still caused a small empty context menu to be visible. After changing its visibility attribute, it was truly disabled.
IsEnabled = false on the ContextMenu?
Edit: As there appear to be closing problems when doing this i would suggest a container style:
<ContextMenu>
<ContextMenu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="IsEnabled" Value="False"/>
</Style>
</ContextMenu.ItemContainerStyle>
<MenuItem Header="Test"/>
</ContextMenu>
Of course the actual value can be bound as well but in the container style the context is the individual item, so to bind to the parent context a RelativeSource binding is necessary (unless the data object also has a connection to the parent).
The entire context menu can be disabled at the root of the ContextMenu by setting the IsEnabled property to false; there is no need to loop through each menu item in code.
<ContextMenu IsEnabled="False">
Or
<ContextMenu IsEnabled={Binding Path=SomeModelBooleanProperty}">
This will enable the context menu to be viewed, but all items will be disabled.
I used ContextMenu="{x:Null}" to disable the Context Menu in a TextBox.
Here is how I solve my question.
Still use ContextMenuOpening event. Use a loop.
This why can help me disable certain context menu item in code, but not in XAML.
private void SetContextMenuItemsEnableStatus(object sender)
{
FrameworkElement element = sender as FrameworkElement;
if (element == null)
{
return;
}
ContextMenu contextMenu = element.ContextMenu;
if (contextMenu == null)
return;
//Use this way.
//You can disable every item or certain item in context menu.
foreach (Control item in contextMenu.Items)
{
item.IsEnabled = false;
}
}
Here is how I solve my question.
<ContextMenu x:Key="TreeViewEmptyContextMenu" Width="0" Height="0"/>
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.
I have have a MenuItem that creates its sub-menu-items dynamicly from the ItemsSource-property.
For grouping, I have Separators in the menu. The separator is created for each null-entry in the ItemsSource-collection by a ControlTemplate of the MenuItem.ItemContainerStyle.
This works fine, however has the separator not the same optical style as the other separators have which are placed in a the Items-collection of a menu.
Is there a way to change the look of the separator so that it looks equal to the "normal" menu-item-separators?
Here is the code I use:
<MenuItem.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Title}"/>
<Setter Property="Command" Value="{Binding Command}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding }" Value="{x:Null}">
<Setter Property="Template" >
<Setter.Value>
<ControlTemplate>
<Separator /> <!-- THIS SEPARATOR IS NOT SHOWN AS COMMON MENUITEM-SEPARATORS ARE -->
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</MenuItem.ItemContainerStyle>
There is a Style that is declared in System.Resources with MenuItem.SeparatorStyleKey as the key. The parent MenuItem normally sets the style on children of type Separator, but since yours is a MenuItem, it won't, so you will have to do it manually:
<Separator Style="{StaticResource {x:Static MenuItem.SeparatorStyleKey}}" />
You may also want to read Bea Stollnitz's blog entry "How do I insert Separator objects in a data bound MenuItem?" for another approach.
Try wrapping the Seperator in a MenuItem
<ControlTemplate>
<MenuItem>
<MenuItem.Header>
<Separator />
</MenuItem.Header>
</MenuItem>
</ControlTemplate>