Reputation: 1179
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?
Upvotes: 4
Views: 2378
Reputation: 505
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?
Upvotes: 1
Reputation: 21
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.
Upvotes: 2