Binding Items collection on Menu to be shown on MenuItem Popup - c#

I have the need to have a custom Menu (AMTMenu class inheriting Menu plus some additional DependencyProperties) with a MenuItem (a hamburger button actually) with dynamic children, since this menu is to be reused in a lot of layouts. Other than that, it should show other 5 TopLevel menu items that display info contained on the DataContext without any children attached and a refresh button. It's working fine except for the sub menu part which is not being shown when I click the hamburger MenuItem because I can't seem to bind the items correctly. Here's the code I have so far:
<Menu.Template>
<ControlTemplate>
<Grid Name="ContentGrid"
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"
IsItemsHost="True">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="HamburgerButtonColumn" Width="5*" />
<ColumnDefinition x:Name="ButtonsColumn" Width="90*" />
<ColumnDefinition x:Name="RefreshButtonColumn" Width="5*"/>
</Grid.ColumnDefinitions>
<MenuItem Foreground="{DynamicResource BlackBrush}"
Focusable="False"
Template="{DynamicResource MainMenuButtonTemplate}">
<MenuItem.Icon>
<iconPacks:PackIconMaterial Kind="Menu"
HorizontalAlignment="Left"
VerticalAlignment="Center"
MinHeight="20" />
</MenuItem.Icon>
</MenuItem>
<UniformGrid Name="ButtonsUniformGrid"
Grid.Column="1"
Columns="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:AMTMenu}}, Path=ButtonCount}"
Rows="1"
HorizontalAlignment="Stretch">
<MenuItem Grid.Column="0"
Template="{DynamicResource OiButtonsTemplate}"
Foreground="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Converter={StaticResource OiMainMenuButtonsColorBrushConverter}}"
Focusable="False"
Command="{Binding ShowRefreshDataCommand}"
CommandParameter="Button1">
<MenuItem.Tag>
<MultiBinding Converter="{StaticResource MainMenuButtonsTextConverter}" ConverterParameter="INC">
[ ... MultiBinding logic ... ]
</MultiBinding>
</MenuItem.Tag>
</MenuItem>
[ ... XAML Code for the other 4 MenuItems ... ]
</UniformGrid>
<DockPanel Name="PART_Refresh"
Grid.Column="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
[ ... XAML Code for the refresh button ... ]
</DockPanel>
</Grid>
</ControlTemplate>
</Menu.Template>
As for the hamburger MenuItem, I have the following template:
<ControlTemplate x:Key="MainMenuButtonTemplate"
TargetType="{x:Type MenuItem}">
<Grid SnapsToDevicePixels="true"
HorizontalAlignment="Stretch">
<StackPanel Background="{TemplateBinding Background}"
VerticalAlignment="Center"
HorizontalAlignment="Center">
<ContentControl x:Name="PART_Button"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}"
Content="{TemplateBinding Icon}"
Focusable="False" />
</StackPanel>
<Popup x:Name="PART_Popup"
AllowsTransparency="true"
Focusable="false"
HorizontalOffset="1"
IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}"
PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}"
Placement="Bottom"
VerticalOffset="-1">
<Border BorderThickness="2"
BorderBrush="White"
Background="{TemplateBinding Background}">
<ScrollViewer x:Name="SubMenuScrollViewer"
CanContentScroll="true"
Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid RenderOptions.ClearTypeHint="Enabled">
<ItemsPresenter x:Name="ItemsPresenter"
KeyboardNavigation.DirectionalNavigation="Cycle"
Grid.IsSharedSizeScope="true"
Margin="2"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</Border>
</Popup>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource AccentColorBrush}" TargetName="PART_Button"/>
<Setter Property="Background" Value="{DynamicResource GrayBrush}" TargetName="PART_Button"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
Finally, I'm declaring the Menu and submenu with the following XAML:
<local:AMTMenu x:Name="MainMenu"
DockPanel.Dock="Top"
DataContext="{Binding CurrentModel}"
IsButton1Visible="True"
IsButton2Visible="True"
IsButton3Visible="True"
IsButton4Visible="True"
IsButton5Visible="False">
<MenuItem Header="Item 1" />
<Separator />
<MenuItem Header="Item 2" />
<Separator />
<MenuItem Header="Item 3" />
</local:AMTMenu>
How can I bind the Items collection on the Menu to be shown on the hamburger MenuItem popup?

So I found the problem, posting here to help anyone who has a similar problem... The issue was that the hamburger MenuItem was declared on the template so, the Menu wasn't getting any children and consequentely not firing the IsSubmenuOpen property on the MenuItem. After I realized this, the solution was pretty simple, replaced the MenuItem on the Template with an ItemsPresenter and moved the MenuItem to the Menu content. Also, and since the Menu now has Items defined in its class, I can't declare the sub menu as I was doing previously, it would only replace my default item, so I had to use a new DependencyProperty called SubMenuItems.
Here's the final code:
AMTMenu.xaml
<Menu>
<Menu.Template>
<ControlTemplate>
<Grid Name="ContentGrid"
Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"
IsItemsHost="True">
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="HamburgerButtonColumn" Width="5*" />
<ColumnDefinition x:Name="ButtonsColumn" Width="90*" />
<ColumnDefinition x:Name="RefreshButtonColumn" Width="5*"/>
</Grid.ColumnDefinitions>
<ItemsPresenter x:Name="ItemsPresenter"
HorizontalAlignment="Center"
VerticalAlignment="Center"
KeyboardNavigation.DirectionalNavigation="Cycle"
Grid.IsSharedSizeScope="true"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
KeyboardNavigation.TabNavigation="Cycle" />
<UniformGrid Name="ButtonsUniformGrid"
Grid.Column="1"
Columns="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:AMTMenu}}, Path=ButtonCount}"
Rows="1"
HorizontalAlignment="Stretch">
<MenuItem Grid.Column="0"
Template="{DynamicResource OiButtonsTemplate}"
Foreground="{Binding RelativeSource={RelativeSource Self}, Path=Tag, Converter={StaticResource OiMainMenuButtonsColorBrushConverter}}"
Focusable="False"
Command="{Binding ShowRefreshDataCommand}"
CommandParameter="Button1">
<MenuItem.Tag>
<MultiBinding Converter="{StaticResource MainMenuButtonsTextConverter}" ConverterParameter="INC">
[ ... MultiBinding logic ... ]
</MultiBinding>
</MenuItem.Tag>
</MenuItem>
[ ... XAML Code for the other 4 MenuItems ... ]
</UniformGrid>
<DockPanel Name="PART_Refresh"
Grid.Column="2"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
[ ... XAML Code for the refresh button ... ]
</DockPanel>
</Grid>
</ControlTemplate>
</Menu.Template>
<MenuItem Foreground="{DynamicResource BlackBrush}"
Focusable="False"
Template="{DynamicResource MainMenuButtonTemplate}"
AllowDrop="True"
ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=local:AMTMenu}, Path=SubMenuItems}">
<MenuItem.Icon>
<iconPacks:PackIconMaterial Kind="Menu" MinHeight="20" />
</MenuItem.Icon>
</MenuItem>
</Menu>
Menu declaration on parent View:
<local:AMTMenu x:Name="MainMenu"
DockPanel.Dock="Top"
DataContext="{Binding CurrentModel}"
IsButton1Visible="True"
IsButton2Visible="True"
IsButton3Visible="True"
IsButton4Visible="True"
IsButton5Visible="False">
<local:AMTMenu.SubMenuItems>
<local:SubMenuItemsCollection>
<MenuItem Header="Item 1" />
<Separator />
<MenuItem Header="Item 2" />
<Separator />
<MenuItem Header="Item 3" />
</local:SubMenuItemsCollection>
</local:AMTMenu.SubMenuItems>
</local:AMTMenu>
Where SubMenuItemsCollection is just a class that derives from ObservableCollection
public class SubMenuItemsCollection : ObservableCollection<FrameworkElement> { }
Hope this helps someone in the future ;)

Related

Extend LayoutAnchorable to have use its own style

I am using AvalonDock in my application to have a Visual Studio look and feel. I would like to add some buttons and other controls to the header of the LayoutAnchorableControl as well as add some menu items to the drop down. I only want this to affect certain controls and not the entire layout.
I've been able to add buttons and controls to specific LayoutAnchorableControls by adding methods to the LayoutAnchorable that check for certain criteria and adding the controls to the theme. However, I feel there is a more robust solution I have yet to stumble on.
If you are using MVVM approach, you don't need to add methods to LayoutAnchorableControls. You can get it simply editing AvalonDock style.
For example, you may edit the LayoutDocumentTabItem style like the following:
<Style TargetType="{x:Type avalonDockControls:LayoutDocumentTabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type avalonDockControls:LayoutDocumentTabItem}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="20" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!-- Following border is required to catch mouse events -->
<Border Grid.ColumnSpan="5" Background="Transparent" />
<TextBlock Grid.Column="0" Visibility="{Binding LayoutItem.Model.IsStatusQuadStringVisible,
RelativeSource={RelativeSource TemplatedParent}, Converter={StaticResource BoolToVisibilityConverter}}"
Text="{Binding LayoutItem.Model.StatusQuadString,
RelativeSource={RelativeSource TemplatedParent}}" FontSize="{StaticResource SrkMainTouchControlFontSize}" HorizontalAlignment="Left" VerticalAlignment="Center" TextTrimming="CharacterEllipsis"/>
<ContentPresenter HorizontalAlignment="Center"
Grid.Column="2"
VerticalAlignment="Center"
Content="{Binding Model,
RelativeSource={RelativeSource TemplatedParent}}"
ContentTemplate="{Binding DocumentHeaderTemplate,
Mode=OneWay,
RelativeSource={RelativeSource AncestorType={x:Type avalonDock:DockingManager},
Mode=FindAncestor}}"
ContentTemplateSelector="{Binding DocumentHeaderTemplateSelector,
Mode=OneWay,
RelativeSource={RelativeSource AncestorType={x:Type avalonDock:DockingManager},
Mode=FindAncestor}}" />
<!-- region TabItem Buttons -->
<StackPanel Grid.Column="4" Orientation="Horizontal"
HorizontalAlignment="Right"
VerticalAlignment="Center">
<Button Margin="2,0"
Command="{Binding LayoutItem.Model.MyCustomCommand, RelativeSource={RelativeSource TemplatedParent}}"
Style="{StaticResource ButtonAvalonDocumentStyleKey}">
<Button.ToolTip>
<PriorityBinding>
<Binding Path="LayoutItem.Model.MyCustomCommand" RelativeSource="{RelativeSource TemplatedParent}" IsAsync="True"/>
</PriorityBinding>
</Button.ToolTip>
<Path Data="{StaticResource SrkGeometryMyCustomCommand}" Stretch="Uniform" Margin="5,0" Style="{StaticResource PathAvalonDocumentStyleWithStrokeKey}" />
</Button>
</StackPanel>
<!-- endregion TabItem Buttons -->
</Grid>
</Border>
</Setter.Value>
</Setter>
</Style>
By doing this, you are adding a new custom Button to the tabbed Doc's title, binded to an ICommand named MyCustomCommand.
Furthermore, you may adding DataTrigger to the style binded to a Visibility property on the ViewModel that can handle button visibility, based on the business logic of your application.
I hope it helps.

Custom MenuItem style for ContextMenu?

I need to create a custom style for MenuItem with a set of ControlTemplate per each MenuItem Role. So, I decided to use this approach from msdn
But, there's one problem - I want to get the same appearance in Popup.
Unfortunately, the appearance is different like on the picture below:
Example of code:
<Window x:Class="ExporerSubMenu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ExporerSubMenu"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="1000">
<Window.Resources>
<!-- Copy all styles for MenuItem ControlTemplate and Brushes -->
<!-- https://msdn.microsoft.com/fr-fr/library/ms747082(v=vs.85).aspx -->
</Window.Resources>
<Grid Background="LightBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBox Text="Local (right click)" FontSize="16" Grid.Column="0">
<TextBox.ContextMenu>
<ContextMenu>
<MenuItem Header="Restore...">
<MenuItem Header="to desktop" />
<MenuItem Header="to another folder" />
<MenuItem Header="db schema and data..." />
</MenuItem>
<MenuItem Header="to .bac file">
<MenuItem Header="to desktop" />
<MenuItem Header="to another folder" />
</MenuItem>
<MenuItem Header="to db files">
<MenuItem Header="to desktop" />
<MenuItem Header="to another folder" />
</MenuItem>
<MenuItem Header="Export data">
<MenuItem Header="db schema to desktop" />
<MenuItem Header="db schema and data..." />
</MenuItem>
<MenuItem Header="Remove" />
</ContextMenu>
</TextBox.ContextMenu>
</TextBox>
</Grid>
</Window>
Now, I have only one solution - to draw rectangles (from Blend)
<Popup x:Name="PART_Popup" AllowsTransparency="True" Focusable="False" HorizontalOffset="-2" IsOpen="{Binding IsSubmenuOpen, RelativeSource={RelativeSource TemplatedParent}}" PopupAnimation="{DynamicResource {x:Static SystemParameters.MenuPopupAnimationKey}}" Placement="Right" VerticalOffset="-3">
<Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent">
<Border x:Name="SubMenuBorder" BorderBrush="#FF959595" BorderThickness="1" Background="WhiteSmoke">
<ScrollViewer x:Name="SubMenuScrollViewer" Margin="1,0" Style="{DynamicResource {ComponentResourceKey ResourceId=MenuScrollViewer, TypeInTargetAssembly={x:Type FrameworkElement}}}">
<Grid x:Name="Grid2" RenderOptions.ClearTypeHint="Enabled">
<Canvas x:Name="Canvas" HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="OpaqueRect" Fill="WhiteSmoke" Height="{Binding ActualHeight, ElementName=SubMenuBorder}" Width="{Binding ActualWidth, ElementName=SubMenuBorder}"/>
</Canvas>
<Rectangle x:Name="Rectangle" Fill="#FFF1F1F1" HorizontalAlignment="Left" Margin="1,2" RadiusY="2" RadiusX="2" Width="28"/>
<Rectangle x:Name="Rectangle1" Fill="#FFE2E3E3" HorizontalAlignment="Left" Margin="29,2,0,2" Width="1"/>
<Rectangle x:Name="Rectangle2" Fill="White" HorizontalAlignment="Left" Margin="30,2,0,2" Width="1"/>
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Cycle" Grid.IsSharedSizeScope="True" Margin="2" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" KeyboardNavigation.TabNavigation="Cycle"/>
</Grid>
</ScrollViewer>
</Border>
</Themes:SystemDropShadowChrome>
</Popup>
Is there any another solution to solve this ?

Menuitem to cut part of the text

The text that is in the MenuItem Header is getting a hidden part, as shown in the image below. The full text is "Informações de Pagamento", but the rest is hidden. I need this component to be this size, width =240
My axml file:
<Image.ContextMenu>
<ContextMenu HorizontalAlignment="Left" Width="240">
<MenuItem x:Name="infoPagamento" Header="_Informações de Pagamento" Cursor="Hand" ToolTip="Online" Click="statusOn_Click" Background="White" Margin="5" >
<MenuItem.Icon>
<Image Source="../Imagens/icons/menuusuario/icon_financeiro.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="alteracaoPlano" Header="Alteração de plano" Cursor="Hand" ToolTip="Alteração de plano" Click="statusAusente_Click" Background="White" Margin="5">
<MenuItem.Icon>
<Image Source="../Imagens/icons/menuusuario/icon_tarefa.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="Relatorios" Header="Relatórios" Cursor="Hand" ToolTip="Ocupado" Click="statusOcupado_Click" Background="White" Margin="5">
<MenuItem.Icon>
<Image Source="../Imagens/icons/menuusuario/icon_relatorios.png" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem x:Name="Ajuda" Header="Ajuda" Cursor="Hand" ToolTip="Offline" Click="statusOff_Click" Background="White" Margin="5">
<MenuItem.Icon>
<Grid>
<Ellipse Width="20" Height="20" Fill="#48026E" />
<Label Content="?" Padding="0"
VerticalAlignment="Center" HorizontalAlignment="Center"
Foreground="White" FontSize="14" Cursor="Hand"/>
</Grid>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</Image.ContextMenu>
My Resource:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type ContextMenu}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContextMenu}">
<Border x:Name="Border"
Background="White"
BorderThickness="1" BorderBrush="Transparent"
Margin="3" CornerRadius="10">
<StackPanel IsItemsHost="True"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I had similar problem for Menu with drop down style. The problem is in reserved space for shortcut like CTRL+D (input gesture text). To overcome limitation I had to set menu item width to fixed size, override menuitem header with text block, set its width to auto (fixed width did not work like expected) and set negative margin for textblock (its size can be different for your problem).
Some short example:
<Menu IsMainMenu="True" Height="auto" Width="220" Margin="0" VerticalAlignment="Center" VerticalContentAlignment="Stretch" HorizontalAlignment="Center" HorizontalContentAlignment="Stretch">
<MenuItem BorderThickness="0" Width="220" Margin="0" VerticalAlignment="Center" VerticalContentAlignment="Stretch" HorizontalAlignment="Left" HorizontalContentAlignment="Stretch">
<MenuItem.Icon>
<Ellipse Width="25" Height="25" HorizontalAlignment="Center" Stretch="Uniform">
<Ellipse.Fill>
<ImageBrush x:Name="imgAvatar" ImageSource="..." TileMode="Tile" Stretch="UniformToFill" />
</Ellipse.Fill>
</Ellipse>
</MenuItem.Icon>
<MenuItem.Header>
<TextBlock Text="Some long long text" Width="auto" TextWrapping="Wrap" Margin="0,0,-75,0" VerticalAlignment="Center" TextAlignment="Left" HorizontalAlignment="Left"/>
</MenuItem.Header>
<MenuItem BorderThickness="0" Width="220" Margin="0" VerticalAlignment="Center" VerticalContentAlignment="Stretch" HorizontalAlignment="Left" HorizontalContentAlignment="Stretch">
<MenuItem.Icon>
<Ellipse Width="25" Height="25" HorizontalAlignment="Center" Stretch="Uniform">
<Ellipse.Fill>
<ImageBrush x:Name="imgAvatar" ImageSource="..." TileMode="Tile" Stretch="UniformToFill" />
</Ellipse.Fill>
</Ellipse>
</MenuItem.Icon>
<MenuItem.Header>
<TextBlock Text="Some long long text 2" Width="auto" TextWrapping="Wrap" Margin="0,0,-75,0" VerticalAlignment="Center" TextAlignment="Left" HorizontalAlignment="Left"/>
</MenuItem.Header>
</MenuItem>
</MenuItem>
</Menu>
Try setting the width of MenuItem as "Auto"

Adding combobox to Ribbon Control in XAML

I have a WPF Application with a Ribbon Control. I want to add a ComboBox, to show the logged in user next to the help button. But when I try to add the ComboBox, it is created as a Tab.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Ribbon x:Name="RibbonWin" SelectedIndex="0" Margin="0,0,0,113">
<Ribbon.HelpPaneContent>
<RibbonButton SmallImageSource="Images\help.png"></RibbonButton>
</Ribbon.HelpPaneContent>
<RibbonComboBox>
<ComboBoxItem Content="Test1"/>
</RibbonComboBox>
<RibbonTab Header="Home" KeyTip="H" Margin="0,0,0,-1" >
<RibbonGroup x:Name="ClipboardGroup" Header="Clipboard">
<RibbonMenuButton LargeImageSource="Images\paste.jpg" Label="Paste" KeyTip="V">
<RibbonMenuItem ImageSource="Images\paste.jpg" Header="Keep Text Only" KeyTip="T"/>
<RibbonMenuItem ImageSource="Images\paste.jpg" Header="Paste Special..." KeyTip="S"/>
</RibbonMenuButton>
<RibbonButton SmallImageSource="Images\cut.jpg" Label="Cut" KeyTip="X" />
<RibbonButton SmallImageSource="Images\copy.jpg" Label="Copy" KeyTip="C" />
</RibbonGroup>
<RibbonGroup x:Name="Questions" Header="Questions And Answers">
<RibbonMenuButton LargeImageSource="Images\Question.jpg" Label="Questions" KeyTip="V">
<RibbonMenuItem ImageSource="Images\paste.jpg" Header="Add Question" KeyTip="T"/>
<RibbonMenuItem ImageSource="Images\paste.jpg" Header="Paste Special..." KeyTip="S"/>
</RibbonMenuButton>
<RibbonButton SmallImageSource="Images\Save.jpg" Label="Save" KeyTip="X" />
<RibbonButton SmallImageSource="Images\Add.jpg" Label="Add" KeyTip="C" />
</RibbonGroup>
</RibbonTab>
<RibbonTab Header="Insert" KeyTip="I">
</RibbonTab>
<RibbonTab Header="PageLayout" KeyTip="L">
</RibbonTab>
</Ribbon>
</Grid>
Also is there a way to remove the the Application Menu ComboBox on the left that is created by default.
Put a RibbonApplicationMenu into the ApplicationMenu-property and set its Visibility to 'Collapsed'. This will not remove the application menu, but at least it is not longer visible. There is not other way to hide it.
The ComboBox must be inserted into a RibbonTab, so a RibbonTab will be created implicitly if you do not specify anyone.
The following example demonstrates how to hide the application menu and insert a combo box:
<Ribbon>
<Ribbon.ApplicationMenu>
<RibbonApplicationMenu Visibility="Collapsed"></RibbonApplicationMenu>
</Ribbon.ApplicationMenu>
<RibbonTab>
<RibbonGroup>
<RibbonComboBox></RibbonComboBox>
</RibbonGroup>
</RibbonTab>
</Ribbon>
I got it from my friend,
this might help you
Create your own template and add it to Ribbon HelpPaneContentTempalte
<Ribbon.HelpPaneContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Height="24">
<ToggleButton x:Name="btn" >
<TextBlock Text="Operator"/>
</ToggleButton>
<Popup IsOpen="{Binding IsChecked, ElementName=btn}" x:Name="Popup" StaysOpen="False" Placement="Bottom"
PlacementTarget="{Binding ElementName=btn}" Height="120" Width="150" HorizontalOffset="-90" >
<Popup.Resources>
<Style x:Key="LinkButton" TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<TextBlock>
<ContentPresenter />
</TextBlock>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Blue" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Popup.Resources>
<Border BorderBrush="Gray" BorderThickness="2" Background="White" >
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal" Height="50">
<Image Source="Images\UserPhoto.png" Height="30"/>
<StackPanel VerticalAlignment="Center">
<TextBlock Text="Operator" FontSize="16" Margin="10,0,0,0"/>
<TextBlock Text="Operator#xxx.com" FontSize="10" Foreground="DarkGray" Margin="10,0,0,0"/>
</StackPanel>
</StackPanel>
<Separator Background="LightGray"/>
<StackPanel Height="30">
<Button x:Name="btnAccountSettings" Content="Account Settings" Style="{StaticResource LinkButton}" Width="100" Margin="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"></Button>
</StackPanel>
<Separator Background="LightGray"/>
<StackPanel Height="30">
<Button x:Name="btnSwitchAccount" Content="Switch Account" Style="{StaticResource LinkButton}" Width="100" Margin="10,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Center"></Button>
</StackPanel>
</StackPanel>
</Border>
</Popup>
<ContentPresenter Content="{TemplateBinding Property= ContentControl.Content}" />
</StackPanel>
</DataTemplate>
</Ribbon.HelpPaneContentTemplate>
<Ribbon.HelpPaneContent>
<RibbonButton x:Name="btnHelp" SmallImageSource="Images\help.png" />
</Ribbon.HelpPaneContent>

How to disable the 'Select All' button of a DataGrid

Is it possible to disable the "Select all" button in the upper left corner of the WPF DataGrid?
There is a Property HeadersVisibility in DataGrid. It has four values - All, Column, Row, None.
With HeadersVisibility = All, you will get the SelectAll Button.
With HeadersVisibility = Column, you will get only Columns. Not the SelectAll Button or Row Headers to select a complete row.
With HeadersVisibility = Row, you will get only Row headers to select whole row. Not the SelectAll Button or Columns.
With HeadersVisibility = None, you will get nothing. All the headers will be hidden.
I hope this helps you.
After using Snoop to analyze the Visual Tree of a test app I put together, I came up with this solution using the DataGrid_Loaded event):
private void TheGrid_Loaded(object sender, RoutedEventArgs e) {
var dataGrid = (DataGrid)sender;
var border = (Border)VisualTreeHelper.GetChild(dataGrid, 0);
var scrollViewer = (ScrollViewer)VisualTreeHelper.GetChild(border, 0);
var grid = (Grid)VisualTreeHelper.GetChild(scrollViewer, 0);
var button = (Button)VisualTreeHelper.GetChild(grid, 0);
button.IsEnabled = false;
}
There may be a more elegant XAML only solution out there, but this is what came to mind first, and it seems to work well enough (I'm obviously not doing any Exception handling either).
Note: I haven't played around with disabling/re-enabling the DataGrid to make sure that the select all button stays disabled. If it doesn't stay disabled, then you may want to also hook into the DataGrid_IsEnabledChanged event.
Hope this helps!!
Add a commandbinding to the SelectAll Command and return false in the CanExecute to disable the selectall button.
see: Event for Select All: WPF Datagrid
If you don't need extended selection in your DataGrid (i.e. switch to single cell selection), you may set:
<DataGrid SelectionMode="Single">
It disables also SelectAll button in top-left corner.
Based on this answer, you can keep your headers and selection mode.
Inside the resources of your user control put :
<Style x:Key="{ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}"
TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<!-- an empty ControlTemplate is fine -->
<ControlTemplate TargetType="{x:Type Button}" />
</Setter.Value>
</Setter>
</Style>
With a little bit of more work, you can add a ToolTip to help the user to discover Ctrl and Shift.
<Style x:Key="{ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}"
TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<!-- an empty ControlTemplate is fine -->
<ControlTemplate TargetType="{x:Type Button}">
<DockPanel HorizontalAlignment="Center"
IsHitTestVisible="False"
VerticalAlignment="Center">
<TextBlock FontSize="18"
FontWeight="ExtraBlack"
Text="ⓘ"
TextAlignment="Center"
ToolTip="{StaticResource DataGridHowTo}" />
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
For the checkbox in the row headers see this post.
I would change the Control Template of DataGrid.
Needs to disable this button inside of template.
This is DataGrid ControlTemplate:
<ControlTemplate TargetType="{x:Type DataGrid}">
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Padding="{TemplateBinding Padding}"
SnapsToDevicePixels="True">
<ScrollViewer x:Name="DG_ScrollViewer"
Focusable="false">
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Button Command="{x:Static DataGrid.SelectAllCommand}"
Focusable="false"
Style="{DynamicResource {ComponentResourceKey ResourceId=DataGridSelectAllButtonStyle, TypeInTargetAssembly={x:Type DataGrid}}}"
Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.All}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
Width="{Binding CellsPanelHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
<DataGridColumnHeadersPresenter x:Name="PART_ColumnHeadersPresenter"
Grid.Column="1"
Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Column}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter"
CanContentScroll="{TemplateBinding CanContentScroll}"
Grid.ColumnSpan="2"
Grid.Row="1" />
<ScrollBar x:Name="PART_VerticalScrollBar"
Grid.Column="2"
Maximum="{TemplateBinding ScrollableHeight}"
Orientation="Vertical"
Grid.Row="1"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
ViewportSize="{TemplateBinding ViewportHeight}" />
<Grid Grid.Column="1"
Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding NonFrozenColumnsViewportHorizontalOffset, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollBar x:Name="PART_HorizontalScrollBar"
Grid.Column="1"
Maximum="{TemplateBinding ScrollableWidth}"
Orientation="Horizontal"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
ViewportSize="{TemplateBinding ViewportWidth}" />
</Grid>
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
Disable the button it manually and assign this ControlTemplate to your DataGrid.

Categories

Resources