Need to change menu item popup direction in wpf - wpf

I docked the menu control in the bottom of page, but it expands down. Can anyone help to expand it upwards. I need to expand towards top
Thanks in advance

<Menu>
<MenuItem x:Name="menuitem"/>
</Menu>
public MainWindow()
{
InitializeComponent ();
menuitem.ApplyTemplate ();
Popup pop = menuitem.Template.FindName ( "PART_Popup", menuitem ) as Popup;
if ( pop != null ) pop.Placement = PlacementMode.Top;
}

I added this code in the menu
<Menu.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation = "Vertical" VerticalAlignment="Bottom" />
</ItemsPanelTemplate>
</Menu.ItemsPanel>
It is done

Related

Why is Canvas covering peer controls in Dockpanel?

Why is the Canvas covering the other Children of the Dock Panel?
I'm setting up a menu bar at the top of the client area and a status bar at the bottom of the client area of the window as per standard convention in xaml as follows:
<Window x:Class="RichCoreW.ScenEditWnd"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ScenEditWnd" Height="490" Width="776" HorizontalAlignment="Right">
<DockPanel Name="mapDockP">
<Menu IsMainMenu="True" DockPanel.Dock="Top">
<MenuItem Header="File">
<MenuItem Header="Save" Name="menuISave" Click="menuISave_Click"/>
<MenuItem Header="Make Playable" Click="MakePlayable" />
</MenuItem>
<MenuItem Command="ApplicationCommands.Help" />
</Menu>
<StackPanel DockPanel.Dock="Bottom" Name="stackPanel1" Orientation="Horizontal" background="Yellow">
<Label Content="Playable:" Name="label1" />
<Label Name="labPlayable" />
</StackPanel>
</DockPanel>
</Window>
Then I add a an instance of the MapCanvEdit Class which inherits from Canvas in C# code as follows. As its the last child to be added to the Dockpanel it should take the remaining space in the Dockpanel. But it covers the menu and status bars as well covering the whole of the client area. To be precise it is the children of the Canvas that cover over the other two Stack Panels. Where the Canvas(MapCanvEdit) is empty you can see the Menu and Status bars:
public partial class ScenEditWnd : Window
{
ScenC scenC;
MapCanvEdit mapCanvE;
public ScenEditWnd(ScenC scenCI)
{
InitializeComponent();
scenC = scenCI;
mapCanvE = new MapCanvEdit(scenC);
mapDockP.Children.Add(mapCanvE);
MouseWheel += mapCanvE.Zoom;
mapCanvE.SizeChanged += delegate { mapCanvE.DrawHexs(); };
ContentRendered += delegate { mapCanvE.DrawHexs(); };
labPlayable.Content = scenC.playable.ToString();
}
}
I've left out the other methods for simplicity. Any help appreciated!
It's just the way Canvas works. It can place its children outside its own area. If you want it to restrict children to bounds set ClipToBounds="True" (see ClipToBounds on MSDN) or use another panel.

Dynamically bound menu

i'm noobie on WPF.
i have this Admin menu include 'manage A','manage B','manage C'
in my XAML
<MenuItem Header="_Admin" Name="adminMenuItem" Visibility="{Binding Path=IsAdmin, Mode=OneWay,}" >
<MenuItem Header="manage A" Command="ShowTab" />
<MenuItem Header="manage B" Command="ShowTab" />
<MenuItem Header="manage C" Command="ShowTab" />
</MenuItem>
in my mainWindow.cs code,
private void ShowTab(MenuItem menuItem)
{
if (menuItem.Header = "manage A")
showTabA();
if (menuItem.Header = "manage B")
showTabB();
if (menuItem.Header = "manage C")
showTabC();
}
can i bind menuitem with commands like that? if not, what's the best way to get the value from different menu items.
Many thanks
Specify a CommandParameter in the MenuItems which identifies the tab, and get that value from the ExecutedRoutedEventArgs.Parameter property, it's cleaner than using the header at the very least.

WPF Popup MenuItem stays highlighted when using arrow keys

After opening a Popup menu programatically, if the user uses up and down arrow keys to move through the menu, menu items get highlighted and they never get unhighlighted. What can I do so that after the user presses the down arrow, the previously highlighted menuitem becomes unhighlighted?
This happens with a very simple Popup menu:
<Grid>
<Button x:Name="Button1" Content="Open Menu"
Click="OnPopupMenuButton_Click"
Height="23" HorizontalAlignment="Left" Margin="69,12,0,0" VerticalAlignment="Top" Width="75" />
<Popup x:Name="MyPopupMenu" StaysOpen="False" >
<StackPanel Orientation="Vertical" Background="White" Margin="0">
<MenuItem x:Name="xAimee" Header="Aimee" Margin="0,2,0,0" />
<MenuItem x:Name="xBarbara" Header="Barbara" />
<MenuItem x:Name="xCarol" Header="Carol" />
<Separator x:Name="xSeparator1" Margin="0,2,2,2"/>
<MenuItem x:Name="xDana" Header="Dana" />
<MenuItem x:Name="xElizabeth" Header="Elizabeth" />
</StackPanel>
</Popup>
</Grid>
Here is how the Popup gets opened:
private void OnPopupMenuButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
Button button = sender as Button;
MyPopupMenu.PlacementTarget = button;
MyPopupMenu.Placement = PlacementMode.Mouse;
MyPopupMenu.IsOpen = true;
MyPopupMenu.StaysOpen = false;
}
I have been following up on archer's suggestion, but I had a few issues. First, I did not want the menu to open on a right-click, partly because I just didn't want it to open on a right-click and partly because I actually need to use PlacementMode.Top, and the context menu kept opening in the standard context-menu place (to the side and down).
So in the end, I did end up using a Context Menu, but I did a couple of special things. First, in the Window constructor, I set the button's ContextMenu to null, to prevent it from opening when right-clicked. Then when the user left-clicks, I programmatically set the ContextMenu to the one that I created in the xaml file. When the menu closes, I set the button's ContextMenu back to null. I tried manipulating the ContextMenu visibility instead, but that did not seem to work as well as setting it to null and back to an object.
Here is the final xaml, not too different from the question exception that I am handling the Closed event for the ContextMenu.
<Button x:Name="xOpenContextMenuButton" Content = "Open Menu"
Click="OnContextMenuButton_Click"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Width="80" Margin="0,0,36,8" Height="23">
<Button.ContextMenu>
<ContextMenu x:Name="xContextMenu" Closed="OnContextMenu_Closed">
<MenuItem x:Name="xAimee" Header="Aimee" />
<MenuItem x:Name="xBarbara" Header="Barbara" />
<MenuItem x:Name="xCarol" Header="Carol" />
<Separator x:Name="xSeparator1" Margin="0,2,2,2" />
<MenuItem x:Name="xDana" Header="Dana" />
<MenuItem x:Name="xElizabeth" Header="Elizabeth" />
</ContextMenu>
</Button.ContextMenu>
</Button>
Here is the code-behind, which changed a lot:
public MainWindow()
{
InitializeComponent();
xOpenContextMenuButton.ContextMenu = null;
}
private void OnContextMenuButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
xOpenContextMenuButton.ContextMenu = xContextMenu;
xContextMenu.PlacementTarget = xOpenContextMenuButton;
xContextMenu.Placement = PlacementMode.Top;
xContextMenu.IsOpen = true;
xContextMenu.StaysOpen = false;
}
private void OnContextMenu_Closed(object sender, RoutedEventArgs e)
{
xOpenContextMenuButton.ContextMenu = null;
}
Once again, thanks to archer, because I didn't realize that using Popup was not the normal way to create a popup menu in WPF. I think the root cause of the problem is, a Popup can contain anything -- a label, another button, etc. Popup isn't necessarily expecting embedded MenuItems, so it isn't smart enough to understand that it should switch between my menu items when using the arrow keys. But a ContextMenu expects to have MenuItems in it so it knows how to switch between them.

Change the content of a button at runtime in wpf

I have a button in a wpf (silverlight actually) application.
I want to change the content of this button at runtime in order to add an image to it (for example, if content was "button one", i want the content to become: stackpanel containing image1 + original button text).
Please help.
Check this:
var sp = new StackPanel();
var img = new Image() {Source = ...}
sp.Children.Add(img);
sp.Children.Add("Hello world");
btn.Content = sp; // btn - is the name of your button.
Instead of adding the image, hide and show it using BooleanToVisibilityConverter. ShowImage is a bool property that you set to true/false to show/hide the image.
<Button>
<StackPanel Orientation="Horizontal">
<Image Visibility="{Binding Path=ShowImage, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<TextBlock Margin="5,0,0,0" Text="button one" />
</StackPanel>
</Button>

constrain StackPanel's width to smallest child element

How can I constrain a vertical WPF StackPanel's width to the most narrow item it contains. The StackPanel's width must not be greater than the width of any other child element.
Unfortunately the IValueConverter approach will not always work; if the children are added to StackPanel statically, for example, the child collection will be empty at the time of binding (so I discovered). The simplest solution is to create a custom panel:
public class ConstrainedStackPanel : StackPanel
{
public ConstrainedStackPanel()
{
}
protected override Size MeasureOverride(Size constraint)
{
foreach (var item in this.Children)
{
// FrameworkElement has the Width property we care about.
FrameworkElement element = item as FrameworkElement;
if (element != null)
constraint.Width = Math.Min(element.Width, constraint.Width);
}
return base.MeasureOverride(constraint);
}
protected override Size ArrangeOverride(Size arrangeSize)
{
foreach (var item in this.Children)
{
// FrameworkElement has the Width property we care about.
FrameworkElement element = item as FrameworkElement;
if (element != null)
arrangeSize.Width = Math.Min(element.Width, arrangeSize.Width);
}
return base.ArrangeOverride(arrangeSize);
}
}
You can use the panel as illustrated by the following XAML:
<StackPanel Margin="5">
<TextBlock Text="StackPanel:" FontWeight="Bold" />
<StackPanel x:Name="panelA">
<Button Width="100" Content="100" />
<Button Width="200" Content="200" />
<Button Width="300" Content="300" />
<Button Width="400" Content="400" />
</StackPanel>
<TextBlock Text="ConstrainedStackPanel:" FontWeight="Bold" Margin="0,10,0,0" />
<l:ConstrainedStackPanel x:Name="panelB">
<Button Width="100" Content="100" />
<Button Width="200" Content="200" />
<Button Width="300" Content="300" />
<Button Width="400" Content="400" />
</l:ConstrainedStackPanel>
</StackPanel>
Which will render something like the following:
I hope this helps.
i have tried binding to the ActualWidth property, even creating a converter to offset the value, and this works great with one exception: as you expand the size of the container, the width is updated properly, but when to make the container smaller, the width of the actual content gets smaller, but the "page width" of any scrollviewers will not. i'm sure there's a way to work around this, but i haven't found it.
You can't. A vertically oriented StackPanel will always allocate as much width as its children request.
You'd be best off writing a custom panel to achieve your desired behavior.

Resources