Question

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"
}
Was it helpful?

Solution

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());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top