WPF ToolBar Separator shrinks to nothing when inside a StackPanel - wpf

Given the very simple wpf app
<Window x:Class="Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="800">
<Grid>
<ToolBar Height="50" >
<MenuItem Header="Test1" />
<MenuItem Header="Test2" />
<StackPanel Orientation="Horizontal">
<Separator />
<MenuItem Header="Test3" />
<MenuItem Header="Test4" />
<MenuItem Header="Test5" />
</StackPanel>
</ToolBar>
</Grid>
</Window>
The Separator element shrinks to nothing. If I put the Separator just before the StackPanel begins, it will show up. Why does this happen? Is there a style setting that can be applied somewhere to avoid this?

The StackPanel is changing the orientation of the Separator somehow. Note that if you explicitly tell the Separator to be 20 units wide, the Separator will be a horizontal line instead of a vertical line. That's part of what's going on.
If you apply a LayoutTransform to the Separator, it undoes whatever the StackPanel is doing.
<Separator>
<Separator.LayoutTransform>
<RotateTransform
Angle="90" />
</Separator.LayoutTransform>
</Separator>
I don't understand the need for a StackPanel, though.

Separators default to Horizontal orientation.
Separators placed directly inside a ToolBar have their styles changed, because Toolbar overrides the default styles of its items. Separators placed elsewhere get the default style of a separator. So you will need to style the separator yourself if you vwant to keep it inside the StackPanel.
This CodeProject discussion includes sample code for accomplishing this.
Reference: WPF Unleashed by Adam Nathan, page 117.

ToolBars are funny about what you put inside. They get funny when all the elements aren't direct children of the ToolBar. The grouping elements are ToolBarTray (group of toolbars), ToolBar, and ToolBarPanel (logical, for collapsing overflow). This is what WPF wants to see:
<Grid>
<ToolBarTray>
<ToolBar Height="Auto">
<ToolBarPanel Orientation="Horizontal" ToolBar.OverflowMode="AsNeeded"/>
<MenuItem Header="Test1" />
<Separator/>
<MenuItem Header="Test2" />
</ToolBar>
<ToolBar Height="Auto">
<ToolBarPanel ToolBar.OverflowMode="Never"/>
<MenuItem Header="Test3" />
<MenuItem Header="Test4" />
<Separator/>
<MenuItem Header="Test5" />
<ToolBarPanel ToolBar.OverflowMode="AsNeeded"/>
<MenuItem Header="Test6" />
<MenuItem Header="Test7" />
</ToolBar>
</ToolBarTray>
</Grid>

Related

wpf how to update Window

I have made my application multilingual. It changes it's language when you click the corresponding menuitem. This works fine but my problem comes when my parent window doesn't change it's language (menu is in parent window). All child windows change their language. Is there any way to force window to load again? I have done my application with resx-files and also checked that Thread.CurrentThread.CurrentCulture and Thread.CurrentThread.CurrentUICulture are changed when menuitem is clicked.
Edit:
I have made my own class to do the multilingual part and it is an adaptation from this article's approach: WPF Runtime Localization, it works. Here is a part of my XAML code to show the databindings:
<Window x:Class="Multilingual.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:properties="clr-namespace:Multilingual.Properties"
Height="350" Width="300" Name="mainWindow" ResizeMode="CanMinimize" SizeToContent="Manual" Closing="mainWindow_Closing" KeyDown="mainWindow_KeyDown">
and
<Menu Height="22" Name="menu" Width="{Binding ElementName=mainWindow, Path=Width}" HorizontalAlignment="Left" VerticalAlignment="Top" Background="Snow" BorderThickness="2">
<Menu.BitmapEffect>
<DropShadowBitmapEffect />
</Menu.BitmapEffect>
<MenuItem Header="{x:Static properties:Resources.Menu}">
<MenuItem Header="{x:Static properties:Resources.Language}" >
<MenuItem Header="{x:Static properties:Resources.Deutsch}" Name="itemDeutsch" Click="menuItem_Click" />
<MenuItem Header="{x:Static properties:Resources.English}" Name="itemEnglish" Click="menuItem_Click" />
</MenuItem>
<MenuItem Header="{x:Static properties:Resources.Exit}" Click="itemExit_Click"/>
</MenuItem>
</Menu>
So I think it would be enough if I would be able to update the window somehow.
WPF: How to change the CurrentUICulture at runtime
I found a solution. I changed my databindings to look like this:
<MenuItem Header="{Binding Path=Menu, Source={StaticResource Resources}}">
Where "Menu" corresponds the MenuItem's name in resx-file.

WPF Menu: Wrap items

I'm working on a WPF control that gets placed inside a TabControl in another window, and I have a menu that stretches across the top of my custom control with the letters of the alphabet as such (for indexing purposes):
<UserControl x:Class="thispageclass"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<Grid>
<StackPanel Orientation="Vertical">
<Menu Name="mnu">
<MenuItem Header="A" />
<MenuItem Header="B" />
<MenuItem Header="C" />
...
<MenuItem Header="Y" />
<MenuItem Header="Z" />
</Menu>
[other elements]
</StackPanel>
</Grid>
</UserControl>
If all the letters are present, the menu gets wider than the window so you can't see the last few items without making the window wider. It seems like it should be trivial to make the menu wrap around if the window is too small but I can't seem to figure out how.
Just override the ItemsPanel of your Menu to a WrapPanel
Sample
<Menu.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</Menu.ItemsPanel>
I created my own minimal sample which worked, leading me to figuring out it was my custom styles that were messing up my menu.

Property Binding to Static Properties in WPF: Width binding doesn't work

Update: I've corrected the post, so the question is closed.
Expected result:
Menu width must be equal to the main window width.
Here is full code:
<Menu Name="menu1" DockPanel.Dock="Top">
<Menu.Width>
<Binding Path="MainWindow.Width"
Source="{x:Static Application.Current}"
UpdateSourceTrigger="PropertyChanged"/>
</Menu.Width>
<MenuItem Header="File">
<MenuItem Header="Open" />
<MenuItem Header="Close" />
</MenuItem>
</Menu>
The result:
Menu width is equal to content width
Doh,
Dmitry, Application.Current doesn't have a property Width...
Use Grid instead of DockPanel:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Menu Name="menu1" VerticalAlignment="Top">
<MenuItem Header="File">
<MenuItem Header="Open"/>
<MenuItem Header="Close"/>
</MenuItem>
</Menu>
</Grid>
</Page>
Don't overcomplicate things. And I really encourage you to read wonderful Dr. WPF articles: ItemsControl from A to Z
Cheers, Anvaka

WPF menu item with image

How to define MenuItem.Icon so that the MenuItemHeader text would be placed below the menu item image?Thanks for help!
How something along the lines of:
<ContextMenu>
<MenuItem Header="Reports">
<MenuItem.Icon>
<Image Source="/XSoftArt.WPFengine;component/Images/export32x32xp.png"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
The easy way way is to not use the Icon property but to instead put the icon in the Header:
<Menu>
<MenuItem>
<MenuItem.Header>
<StackPanel>
<Image Width="20" Height="20" Source="/XSoftArt.WPFengine;component/Images/export32x32xp.png" />
<ContentPresenter Content="Reports" />
</StackPanel>
</MenuItem.Header>
</MenuItem>
<MenuItem Header="Export" />
<MenuItem Header="New record" />
</Menu>
For this simple case the <ContentPresenter Content="Reports" /> can be replaced with a <TextBlock Text="Reports" /> because that's what ContentPresenter would use to present the string anyway. For more complex Header=, you could use the ContentPresenter as shown.
In the case of StackPanel use Label and not the TextBlock since only Label will allow you to have the mnemonics on the menu, like _Reports.

WPF Focus Navigation Wrapping

Is there a way to force Focus Navigation (as controlled by the Tab key or MoveFocus method) to wrap inside a given container? I have included code which demonstrates this problem below. What is the easiest way to make Tab move focus from TextBox "Charlie" to TextBox "Able" (and visa-versa for Shift+Tab on TextBox "Able") rather than moving it to MenuItem "Alpha"?
<Window x:Class="NavWrapExample.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<DockPanel LastChildFill="True">
<Menu DockPanel.Dock="Top">
<MenuItem Header="Alpha" />
<MenuItem Header="Bravo" />
<MenuItem Header="Charlie" />
</Menu>
<StackPanel>
<TextBox Text="Able" />
<TextBox Text="Baker" />
<TextBox Text="Charlie" />
</StackPanel>
</DockPanel>
</Window>
Use the KeyboardNavigation.TabNavigation attached property, like so:
<StackPanel KeyboardNavigation.TabNavigation="Cycle">
<TextBox Text="Able" />
<TextBox Text="Baker" />
<TextBox Text="Charlie" />
</StackPanel>
Found the answer on Mark Smith's blog.
It sounds like what you want is the same behavior as toolbars: you can tab into them, but once an element within the toolbar gets keyboard focus, focus loops inside. If so, use FocusManager as follows:
<StackPanel FocusManager.IsFocusScope="True">
<!-- Controls go here... -->
</StackPanel>

Resources