I've created a controll menu in WPF. The button in that menu should activate the "Dark mode" that I've already created. Well that's just a simple Click event.
But I'd like to have a CheckBox not a simple Click event.
That's my code in XAML:
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_Settings">
<MenuItem Header="_Darkmode" />
</MenuItem>
</Menu>
</DockPanel>
The C# Code is inconsequential because that's just a sample.
Greetings from the US
Instead of using the Click event:
<Menu>
<MenuItem Header="_Settings">
<MenuItem Header="_Darkmode"
Click="OnDarkmodeClicked"/>
</MenuItem>
</Menu>
You could use the Checked/Unchecked events after setting the IsCheckable property:
<Menu>
<MenuItem Header="_Settings">
<MenuItem Header="_Darkmode"
IsCheckable="True"
Checked="OnDarkmodeChecked"
Unchecked="OnDarkmodeUnchecked"/>
</MenuItem>
</Menu>
Or you could bind IsChecked to a property in your model:
<Menu>
<MenuItem Header="_Settings">
<MenuItem Header="_Darkmode"
IsCheckable="True"
IsChecked="{Binding UseDarkmode}"/>
</MenuItem>
</Menu>
This may not be the best solution, but you could store a boolean elsewhere, and have a menuitem that looks like this:
XAML code
<MenuItem Header="_Blur Background" IsCheckable="True" IsChecked="True" Click="BlurOnOff_Click" InputGestureText="Ctrl+B"></MenuItem>
Then C# code
private void BlurOnOff_Click(object sender, RoutedEventArgs e)
{
blurOn = blurOn ? false : true;
}
The Blur On/Off is just an example. When the function is called, it updates the boolean to be the opposite of what it was before.
Related
Instead of using Alt + F to open the menu "File", I want to change the holy key F1, how do I do that? Thanks!
<Grid>
<Menu Background="Transparent">
<MenuItem x:Name="asd" Header="_File">
<MenuItem x:Name="a" Header="1. _New" InputGestureText="ALT-N" Margin="0,18,0,0"/>
<MenuItem Header="2. _Open" InputGestureText="Alt+O"/>
<MenuItem Header="3. _Close"/>
<MenuItem Header="4. Save"/>
<Separator/>
<MenuItem Header="5. Delete" Margin="0,8,0,0"/>
<MenuItem Header="6. Rename"/>
<Separator/>
<MenuItem Header="7. Print" Margin="0,8,0,8"/>
<Separator/>
<MenuItem Header="8. Format Disk" Margin="0,8,0,8"/>
<Separator/>
<MenuItem Header="9. MINE(Decode)" Margin="0,8,0,8"/>
</MenuItem>
</Menu>
</Grid>
One way of getting the behaviour you desire would be to add an PreviewKeyDown event listener to your Grid or the parent.
<Grid PreviewKeyDown="Grid_PreviewKeyDown">
<Menu Background="Transparent">
<MenuItem x:Name="asd" Header="_File">
<MenuItem x:Name="a" Header="1. _New" InputGestureText="ALT-N" Margin="0,18,0,0"/>
<MenuItem Header="2. _Open" InputGestureText="Alt+O"/>
<MenuItem Header="3. _Close"/>
<MenuItem Header="4. Save"/>
<Separator/>
<MenuItem Header="5. Delete" Margin="0,8,0,0"/>
<MenuItem Header="6. Rename"/>
<Separator/>
<MenuItem Header="7. Print" Margin="0,8,0,8"/>
<Separator/>
<MenuItem Header="8. Format Disk" Margin="0,8,0,8"/>
<Separator/>
<MenuItem Header="9. MINE(Decode)" Margin="0,8,0,8"/>
</MenuItem>
</Menu>
</Grid>
Then in the underlying C# code add the following action event
private void Grid_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.F1) // This filters what key was pressed
{
asd.IsSubmenuOpen = true; // This opens the menu
e.Handled = true; // Setting this to true prevents the any other events from occurring due to the key press
}
}
Inside this combobox I have a menu that contains multiple menus.
This is how it looks:
This is the XAML:
<ComboBox>
<Menu>
<MenuItem Header="Name">
<MenuItem Header="Last" />
<MenuItem Header="First" />
</MenuItem>
</Menu>
<Menu>
<MenuItem Header="Age">
<MenuItem Header="20" />
<MenuItem Header="24" />
</MenuItem>
</Menu>
</ComboBox>
When the user selects "Last"/"First"/"20"/"24" I want the combobox to set its selected item to one of this 4 items.
Is it possible? If yes, how can I do it?
Yes you can do that. But I am not sure if this is the best way cos I dont know your requirement in full.
XAML:
<ComboBox x:Name="cmb1" IsEditable="True" >
<Menu>
<MenuItem Header="Name" >
<MenuItem Click="MenuItem_Click" CommandParameter ="Last" Header="Last"/>
<MenuItem Click="MenuItem_Click" CommandParameter="First" Header="First" />
</MenuItem>
</Menu>
<Menu>
<MenuItem Header="Age">
<MenuItem Header="20" />
<MenuItem Header="24" />
</MenuItem>
</Menu>
</ComboBox>
vb Code:
Private Sub MenuItem_Click(sender As Object, e As RoutedEventArgs)
Me.cmb1.Text = CType(sender, MenuItem).CommandParameter.ToString()
End Sub
c# code :
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MenuItem menuItem = sender as MenuItem;
this.cmb1.Text = menuItem.CommandParameter.ToString();
}
I'd like to get to know how I can set menu entries visible or hidden for certain user roles in XAML code? Eg I have "_MenuEntryForADMIN" which should only visible for user role "admin" and "_MenuEntryForAllUsers" should be visible to all users - role "user".
Here is my XAML code:
<Grid>
<DockPanel>
<MenuItem Header="_MenuEntryForADMIN">
<MenuItem Header="_Master1" Click="btnMaster1_Click">
<MenuItem.Icon>
<Image Source="database.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Master2" Click="btnMaster2_Click">
<MenuItem.Icon>
<Image Source="database.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
<MenuItem Header="_MenuEntryForAllUsers">
<MenuItem Header="_Normal1" Click="btnNormal1_Click">
<MenuItem.Icon>
<Image Source="database.png" />
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="_Normal2" Click="btnNormal2_Click">
<MenuItem.Icon>
<Image Source="database.png" />
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</Menu>
</DockPanel>
</Grid>
The CS-Code contains the information whether a user has the role "admin" or "user" like this:
User userObject;
public MainWindow(User userObject)
{
InitializeComponent();
this.userObject = userObject; // this.userObject.Role is "admin" or "user"
}
In WPF, it is important to 'shape' your data into the correct structure before you try to display it. By this, I mean that you should filter the data, your MenuItems, in your view model or code behind before displaying them, rather than trying to filter them in the UI.
So rather than defining them all in XAML, create some custom data type to data bind to the various MenuItem properties that you are interested in. Then create a DataTemplate and bind a collection of these to the MenuItem.ItemsSource property. You can find out how to do that from my answer to the Dynamically hiding menu items question. In short, it looks something like this:
<DataTemplate x:Key="MenuItemTemplate" DataType="{x:Type MenuItem}">
<MenuItem Command="{Binding Command}" CommandParameter="{Binding CommandParameter}"
Header="{Binding Path=Header}" Visibility="{Binding Visible, Converter={
BooleanToVisibilityConverter}}" ItemsSource="{Binding ChildMenuItems}" />
</DataTemplate>
There are also many examples online of filtering data in collections, so I won't go over all of that here. You can find a short example in the “Hiding” part of List question here on Stack Overflow. Basically, you can use LinQ to select just the admin MenuItems something like this:
ChildMenuItems = new ObservableCollection<YourCustomDataType>(
FullCollection.Where(i = i.Role == "admin").ToList());
I have this Menu in my App:
<Menu Height="23" HorizontalAlignment="Left" Margin="84,66,0,0" Name="menu1" VerticalAlignment="Top" Width="200">
<MenuItem Header="File" />
<MenuItem Header="Youtube" Name="myYouTube" Click="MenuItem_Click">
<MenuItem Header="Login"/>
<MenuItem Header="Logout"/>
</MenuItem>
<MenuItem Header="Help" />
</Menu>
And when i click myYouTube then MenuItem_Click won't fire.
Any idea why i happen?
If you have sub-menu items the event will not be raised se: MenuItem.Click Event
But maybe you could use the SubmenuOpened event se: MenuItem.SubmenuOpened Event
I changed it to the events for WPF now.
I have an image that has a nested context menu defined in the XAML (shown below).
I am trying to use a for loop to find a menu and uncheck it using IsChecked=false.
my code is as follows:
for (int i = 1; i <= 16; i++)
{
MenuItem theMenu = (MenuItem)this.FindName("beat" + i.ToString());
theMenu.IsChecked = false;
}
the above does not work and returns a null.
what am I doing wrong!
excerpt from the XAML
<Image x:Name="Options" Height="35" Source="Images/pad-options-button.png" Stretch="Fill" Width="47" Canvas.Left="740" Canvas.Top="293"
MouseUp="Options_MouseUp">
<Image.ContextMenu>
<ContextMenu>
<MenuItem Header="Beats">
<MenuItem Name="beat1" Header="1" Click="MenuBeats_Click"/>
<MenuItem Name="beat2" Header="2" Click="MenuBeats_Click"/>
<MenuItem Name="beat3" Header="3" Click="MenuBeats_Click"/>
<MenuItem Name="beat4" Header="4" Click="MenuBeats_Click"/>
<MenuItem Name="beat5" Header="5" Click="MenuBeats_Click"/>
<MenuItem Name="beat6" Header="6" Click="MenuBeats_Click"/>
<MenuItem Name="beat7" Header="7" Click="MenuBeats_Click"/>
<MenuItem Name="beat8" Header="8" Click="MenuBeats_Click"/>/>
<MenuItem Name="beat9" Header="9" Click="MenuBeats_Click"/>
<MenuItem Name="beat10" Header="10" Click="MenuBeats_Click"/>
<MenuItem Name="beat11" Header="11" Click="MenuBeats_Click"/>
<MenuItem Name="beat12" Header="12" Click="MenuBeats_Click"/>
<MenuItem Name="beat13" Header="13" Click="MenuBeats_Click"/>
<MenuItem Name="beat14" Header="14" Click="MenuBeats_Click"/>
<MenuItem Name="beat15" Header="15" Click="MenuBeats_Click"/>
<MenuItem Name="beat16" Header="16" Click="MenuBeats_Click"/>
</MenuItem>
<MenuItem Header="Beat Type">
<MenuItem Name="Whole" Header="Whole" Click="MenuBeatType_Click"/>
<MenuItem Name ="Half" Header="Half" Click="MenuBeatType_Click"/>
<MenuItem Name ="Quarter" Header="Quarter" Click="MenuBeatType_Click"/>
<MenuItem Name ="Eighth" Header="Eighth" Click="MenuBeatType_Click"/>
<MenuItem Name ="Sixteenth" Header="Sixteenth" Click="MenuBeatType_Click"/>
</MenuItem>
</ContextMenu>
</Image.ContextMenu>
</Image>
</Canvas>
An other option is to get the context menu from the image.
var items = Options.ContextMenu.Items
foreach(MenuItem item in items)
{
// do your work with the item
}
Be arware that you will have to handle the sub items!
Items will have only 2 items in your case
You have incorrect markup. Last two symbols shouldn't be there:
<MenuItem Name="beat8" Header="8" Click="MenuBeats_Click"/>/>
However, you example perfectly works for me, but with accidental item:
"/>"
Just in the constructor of the class in code behind write NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this)); contextMenu is the name given to context menu of image. Actually ContextMenu is not the part of Visual tree so it cant find the names . but the above line of code will set context menu in the scope of visual tree and hence will find the names. Hope this will help.