2

I'm currently trying to implement a Metro styled Window.
So i've made the following styles inside a ResoruceDictionary:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<!-- Brushes -->
<SolidColorBrush x:Key="BackgroundColor" Color="#FFFFFFFF" />

<!-- Buttons -->
<Style x:Key="MetroControlBoxButton" TargetType="Button">
    <Setter Property="Background" Value="{StaticResource BackgroundColor}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <ContentPresenter />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<!-- Windows -->
<Style x:Key="MetroWindow" TargetType="Window">
    <Setter Property="UseLayoutRounding" Value="True" />
    <Setter Property="WindowStyle" Value="None" />
    <Setter Property="ResizeMode" Value="NoResize" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Window">
                <Grid Background="{StaticResource BackgroundColor}">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="6" />
                        <RowDefinition Height="24" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="24" />
                        <RowDefinition Height="6" />
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="6" />
                        <ColumnDefinition Width="*" />
                        <ColumnDefinition Width="6" />
                    </Grid.ColumnDefinitions>

                    <Rectangle Name="topLeftBorderRectangle" Fill="Red" Grid.Row="0" Grid.Column="0" />
                    <Rectangle Name="topCenterBorderRectangle" Fill="Orange" Grid.Row="0" Grid.Column="1" />
                    <Rectangle Name="topRightBorderRectangle" Fill="Red" Grid.Row="0" Grid.Column="2" />
                    <Rectangle Name="middleLeftBorderRectangle" Fill="Orange" Grid.Row="1" Grid.RowSpan="3" Grid.Column="0" />
                    <Rectangle Name="middleRightBorderRectangle" Fill="Orange" Grid.Row="1" Grid.RowSpan="3" Grid.Column="2" />
                    <Rectangle Name="bottomLeftBorderRectangle" Fill="Red" Grid.Row="4" Grid.Column="0" />
                    <Rectangle Name="bottomCenterBorderRectangle" Fill="Orange" Grid.Row="4" Grid.Column="1" />
                    <Rectangle Name="bottomRightBorderRectangle" Fill="Red" Grid.Row="4" Grid.Column="2" />

                    <Rectangle Name="statusBarRectangle" Fill="Yellow" Grid.Row="3" Grid.Column="1" />

                    <Grid Grid.Row="1" Grid.Column="1">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto" />
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="28" />
                            <ColumnDefinition Width="28" />
                            <ColumnDefinition Width="28" />
                        </Grid.ColumnDefinitions>

                        <Rectangle Name="dragRectangle" Fill="Yellow" Grid.Row="0" Grid.Column="1" />
                        <Button Name="minimizeButton" Content="_" Grid.Row="0" Grid.Column="2" Style="{StaticResource MetroControlBoxButton}" />
                        <Button Name="maximizeButton" Content="[]"  Grid.Row="0" Grid.Column="3" Style="{StaticResource MetroControlBoxButton}" />
                        <Button Name="closeButton" Content="X" Grid.Row="0" Grid.Column="4" Style="{StaticResource MetroControlBoxButton}" />
                    </Grid>

                    <ContentPresenter Grid.Row="2" Grid.Column="1" />
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

</ResourceDictionary>

My problem with is that i'd like to implement the ControlBox buttons (Minimize, Maximize and Close).
I can create three buttons, align them top right. But since my style is inside a ResourceDictionary i have no idea how to implement the click events.

Same goes for resize and dragging the Window. I know how to drag and resize my Window but i need to link it to the Window_MouseLeftButtonDown event, but i have no idea how to link it inside a template.

I saw that i "could" create a class and put my code in it here:
Is it possible to set code behind a resource dictionary in WPF for event handling?
But it seems it's not a good approach.

I thought i might be able to create a MetroWindow and have my other Windows inherit it. But WPF doesn't support Visual Inheritance.

So what would be the best practice so can reuse my Window template on more than one Window throughout my application.

Thanks,
SiriusNik

Community
  • 1
  • 1
SiriusNik
  • 561
  • 2
  • 7
  • 19

1 Answers1

1

I'm a little confused by the button issue. Even though you have created a button in the Template property of the style, you still need to apply that style to a button object which I'm not seeing in your example. The click event or a command would be added to the button element.

For example:

<Button x:Name="testButton" Style="{StaticResource MetroControlBoxButton}" ... />

UPDATE:

To bind to a command in the Window's DataContext from a control template, you may need to add this element to the Button definition:

Command="{Binding Path=DataContext.ClickCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"
Josh
  • 2,955
  • 1
  • 19
  • 28
  • I've updated my original post to add the buttons. So how can my closeButton execute the Close(); method inside a template? – SiriusNik Aug 10 '11 at 20:03
  • Even though it's in a template, since you have defined the button you can perform a Command Binding to perform an action located in the Window's DataContext. I believe this is the only way you can do this because the event will not be found if defined in the ResourceDictionary. If I'm wrong, someone please correct me. I updated my answer below to show an example. – Josh Aug 10 '11 at 20:41
  • From your answer I realized that I was missing some knowledge. After some research I found that I didn't know anything about MVVM! So I've made a MetroWindowViewModel and was able to successfully bind the Command. But one question, if i want to use my Window template on multiple Windows, will i need to make each new Windows ModelView inherit my MetroWindowModelView? – SiriusNik Aug 12 '11 at 18:20
  • You're not forced to inherit that ViewModel. You can attach another instance of it or even a separate ViewModel all together, as long as it has a Command with the same name so the Window can bind to it. – Josh Aug 15 '11 at 16:58
  • @SiriusNik I have encountered the same question as you , Now Can you give an answer on this now? :D . I have searched a lot but got no result. :) – CharlieShi Jul 26 '12 at 15:21