Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Same menubar or toolbar for all windows in a WPF application

Tags:

c#

wpf

I want to create a wpf application with a menubar. The Menubar has some clickable elements, which opens a new window. Because the menubar is the same on every window, I want to create the menubarcode just once.

I read here how to create a menubar (What is the accepted way to get a main window with menubar and toolbar in WPF?):

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="self"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <Menu Grid.Row="0">
            <MenuItem Header="File">
                <MenuItem Header="Open" />
                <MenuItem Header="Close" />
            </MenuItem>
        </Menu>
        <ToolBar Grid.Row="1">
            <Button Content="Foo" />
            <Button Content="Bar" />
        </ToolBar>
    </Grid>
</Window>

I read also the question for the same header an footer for alle wpf windows: Same header & footer in all WPF windows. There they suggest a usercontrol.

The Question How to make a Template Window in WPF? doesn't solve my issue. Is it possible to add clicklistener to the template? I do not want to implement all clicklistener on every window. My menubar/toolbar only opens some other windows. Only for diplaying static content the solution would work.

What is the best practice for this kind of problem?

like image 814
Charlie Avatar asked Oct 31 '25 09:10

Charlie


2 Answers

You can use DataTemplates.

DataTemplate:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:local="clr-namespace:WpfApplication1">
    <DataTemplate DataType="{x:Type local:MenuBar}">
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <Menu Grid.Row="0">
                <MenuItem Header="File">
                    <MenuItem Header="Open" />
                    <MenuItem Header="Close" />
                </MenuItem>
            </Menu>
            <ToolBar Grid.Row="1">
                <Button Content="Foo" />
                <Button Content="Bar" />
            </ToolBar>
        </Grid>
    </DataTemplate>
</ResourceDictionary>

Code behind:

namespace WpfApplication1
{
    public class MenuBar
    {
        //some logic here
    }
}

Example of use in your code:

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Name="self"
    Title="MainWindow" Height="350" Width="525">
    <ContentPresenter Content="{Binding MenuBar}"/>
</Window>

Where Menubar is property of type MenuBar.

like image 129
davlast Avatar answered Nov 03 '25 00:11

davlast


You can create a style where you define template for a window.

<Style x:Key="MyWindowStyle" TargetType="Window">
    //Some other shared properties
    <Setter Property="..." Value="..."/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Window}">
                <StackPanel>
                    //This will represent a header/toolbar
                    <StackPanel />
                    <ContentPresenter />
                    //This will represent a footer
                    <StackPanel />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Add that style to Application Resources:

<Application x:Class="Wpf.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Application.Resources>
        <Style x:Key="MyWindowStyle" TargetType="Window">
            //...
        </Style>
    </Application.Resources>
</Application>

You can use it followingly:

<Window x:Class="Wpf.Views.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:viewModels="clr-namespace:Wpf.ViewModels"
        mc:Ignorable="d"
        Style="{StaticResource MyWindowStyle}"> //We apply that style to this window

    <TextBlock Text="This will be put in 'ContentPresenter' between those stackpanels"/>

</Window>

If your toolbar/header is complicated then you can pull it into separate usercontrol.
If you want to have 'base' window for shared code-behind functionality then take a look at How do I create a base page in WPF?

like image 21
Siim Haas Avatar answered Nov 02 '25 22:11

Siim Haas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!