简体   繁体   中英

How to inherit Button behaviour in WPF style?

I have overriden the WPF default Maximize, Minimize buttons like explained here . But, in my case, instead of using an Image to override background image for that buttons, I wanted to add my own template.

So I created a ResourceDictionary that applies a style for Maximize/Minimize/Restore/Close buttons.

The thing is that I override the template. As an example, see the PART_MINIMIZE button:

 <Button x:Name="PART_MINIMIZE" 
      Width="30"
      Height="20"
      Margin="0,0,4,0"
      HorizontalAlignment="Center" 
      Template="{DynamicResource MinimizeButton}" 
      VerticalAlignment="Center" 
      DockPanel.Dock="Right">
  </Button>

The DynamicResource called MinimizeButton stablishes the full template. The problem comes when I click the button. As I override the Template part, it has no behaviour defined by me by default. But I want to keep Maximize/Minimize/Restore/Close behaviour by default, without overriding it. So...

How can I say in the template to inherit the behaviour of the button? Or how to simulate them?

Thanks!

i think you should not override the template as it looses basic operations of the control what you should is set the contentTemplate not the template as contenttemplate defines how will your button will look like without halting its basic functions..

this is how you can edit the contenttemplate of button..

 <Button Grid.Column="3"  FontSize="22" FontWeight="Light" Opacity="0.5" BorderThickness="0" Margin="15,0,0,0" >
            <Button.ContentTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal" >
                        <TextBlock Text="Search" />
                        <TextBlock Text="&#xE11A;" FontFamily="Segoe UI Symbol" FontSize="22" VerticalAlignment="Center" />
                    </StackPanel>
                </DataTemplate>
            </Button.ContentTemplate>
        </Button>

if you want to set how your button should look like in app.xaml just set it set its datatemplate like this..

        <DataTemplate x:Key="tempbtn">
            <Grid >
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <TextBlock Grid.Row="0" Text="hellotxt" FontSize="30" />
                <TextBlock Grid.Row="1" Text="asdl;fjkladjglkad" FontSize="50" />
            </Grid>
        </DataTemplate>

us this datatemplate on your button in xaml like this..

<Button ContentTemplate="{StaticResource tempbtn}" Width="500" Height="200" />

Operation with the Window should be placed in a special class that would be available from XAML, like that:

Operation Close :

<Trigger Property="IsChecked" Value="True">
    <Setter Property="Controls:WindowBehaviours.Close" Value="True" />
</Trigger>

Operation Hide :

<Trigger Property="IsChecked" Value="True">
    <Setter Property="Controls:WindowBehaviours.Hide" Value="True" />
</Trigger>

This uses ToggleButton because he has property IsChecked accessible via a trigger. These properties - attached depending properties.

Listing of WindowBehaviours class:

public static class WindowBehaviours
{
    // Close the Window
    public static void SetClose(DependencyObject target, bool value)
    {
        target.SetValue(CloseProperty, value);
    }

    public static readonly DependencyProperty CloseProperty =
                                              DependencyProperty.RegisterAttached("Close",
                                              typeof(bool),
                                              typeof(WindowBehaviours),
                                              new UIPropertyMetadata(false, OnClose));

    private static void OnClose(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue is bool && ((bool)e.NewValue))
        {
            Window window = GetWindow(sender);

            if (window != null)
            {
                window.Close();
            }
        }
    }

    // Hide the Window
    public static void SetHide(DependencyObject target, bool value)
    {
        target.SetValue(HideProperty, value);
    }

    public static readonly DependencyProperty HideProperty =
                                              DependencyProperty.RegisterAttached("Hide",
                                              typeof(bool),
                                              typeof(WindowBehaviours),
                                              new UIPropertyMetadata(false, OnHide));

    private static void OnHide(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue is bool && ((bool)e.NewValue))
        {
            Window window = GetWindow(sender);

            if (window != null)
            {
                window.WindowState = WindowState.Minimized;
            }
        }
    }

    // Full the Window
    public static void SetFull(DependencyObject target, bool value)
    {
        target.SetValue(FullProperty, value);
    }

    public static readonly DependencyProperty FullProperty =
                                              DependencyProperty.RegisterAttached("Full",
                                              typeof(bool),
                                              typeof(WindowBehaviours),
                                              new UIPropertyMetadata(false, OnFull));

    private static void OnFull(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue is bool && ((bool)e.NewValue))
        {
            Window window = GetWindow(sender);

            if (window != null)
            {
                window.WindowState = WindowState.Maximized;
            }
        }
    }

    // Set the Window in Normal
    public static void SetNormal(DependencyObject target, bool value)
    {
        target.SetValue(NormalProperty, value);
    }

    public static readonly DependencyProperty NormalProperty =
                                              DependencyProperty.RegisterAttached("Normal",
                                              typeof(bool),
                                              typeof(WindowBehaviours),
                                              new UIPropertyMetadata(false, OnNormal));

    private static void OnNormal(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue is bool && ((bool)e.NewValue))
        {
            Window window = GetWindow(sender);

            if (window != null)
            {
                window.WindowState = WindowState.Normal;
            }
        }
    }

    // Get the Window
    private static Window GetWindow(DependencyObject sender)
    {
        Window window = null;

        if (sender is Window)
        {
            window = (Window)sender;
        }

        if (window == null)
        {
            window = Window.GetWindow(sender);
        }

        return window;
    }
}

Samples of using ToggleButtons with WindowBehaviours class:

CloseButton

     <Style x:Key="ToggleButtonWindowClose" TargetType="{x:Type ToggleButton}">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="SnapsToDevicePixels" Value="True" />

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ToggleButton">                           
                       <Grid>
                            <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />

                            <Border x:Name="BorderClose" Background="Beige" BorderThickness="0" Width="22" Height="22" HorizontalAlignment="Right" Margin="0,6,8,0" VerticalAlignment="Top" Opacity="0" />
                            <Path x:Name="CloseWindow" SnapsToDevicePixels="True" ToolTip="Закрыть окно" Width="18" Height="17" Margin="0,0,10,0" HorizontalAlignment="Right" VerticalAlignment="Center" Stretch="Fill" Fill="#2D2D2D" Data="F1 M 26.9166,22.1667L 37.9999,33.25L 49.0832,22.1668L 53.8332,26.9168L 42.7499,38L 53.8332,49.0834L 49.0833,53.8334L 37.9999,42.75L 26.9166,53.8334L 22.1666,49.0833L 33.25,38L 22.1667,26.9167L 26.9166,22.1667 Z " />
                        </Grid>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="CloseWindow" Property="Fill" Value="#C10000" />
                                <Setter TargetName="BorderClose" Property="Opacity" Value="1" />
                            </Trigger>

                            <Trigger Property="IsChecked" Value="True">
                                <Setter Property="Controls:WindowBehaviours.Close" Value="True" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>    

HideButton

    <Style x:Key="ButtonWindowHide" TargetType="{x:Type ToggleButton}">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="SnapsToDevicePixels" Value="True" />

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ToggleButton">
                        <Grid>
                            <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />

                            <Border x:Name="BorderHide" Background="Beige" BorderThickness="0" Width="22" Height="22" HorizontalAlignment="Right" Margin="0,6,32,0" VerticalAlignment="Top" Opacity="0" />
                            <Path x:Name="HideWindow" SnapsToDevicePixels="True" ToolTip="Скрыть окно" Width="14" Height="19" Margin="0,0,36,0" HorizontalAlignment="Right" VerticalAlignment="Center" Stretch="Fill" Fill="#2D2D2D" Data="F1 M 42,19.0002L 34,19.0002L 34,43.7502L 24,33.7502L 24,44.2502L 38,58.2502L 52,44.2502L 52,33.7502L 42,43.7502L 42,19.0002 Z " />
                        </Grid>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="HideWindow" Property="Fill" Value="#0094FF" />
                                <Setter TargetName="BorderHide" Property="Opacity" Value="1" />
                            </Trigger>

                            <Trigger Property="IsChecked" Value="True">
                                <Setter Property="Controls:WindowBehaviours.Hide" Value="True" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

FullScreenButton

         <Style x:Key="ButtonWindowFull" TargetType="{x:Type ToggleButton}">
            <Setter Property="Background" Value="Transparent" />
            <Setter Property="SnapsToDevicePixels" Value="True" />

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ToggleButton">
                        <Grid>
                            <ContentPresenter x:Name="MyContentPresenter" Content="{TemplateBinding Content}" HorizontalAlignment="Center" VerticalAlignment="Center" />

                            <Border x:Name="BorderFull" Background="Beige" BorderThickness="0" Width="22" Height="22" HorizontalAlignment="Right" Margin="0,6,58,0" VerticalAlignment="Top" Opacity="0" />
                            <Path x:Name="FullWindow" SnapsToDevicePixels="True" Width="19" Height="19" Margin="0,0,60,0" HorizontalAlignment="Right" VerticalAlignment="Center" Stretch="Fill" Fill="#2D2D2D" Data="F1 M 30.25,58L 18,58L 18,45.75L 22,41.75L 22,50.75L 30,42.75L 33.25,46L 25.25,54L 34.25,54L 30.25,58 Z M 58,45.75L 58,58L 45.75,58L 41.75,54L 50.75,54L 42.75,46L 46,42.75L 54,50.75L 54,41.75L 58,45.75 Z M 45.75,18L 58,18L 58,30.25L 54,34.25L 54,25.25L 46,33.25L 42.75,30L 50.75,22L 41.75,22L 45.75,18 Z M 18,30.25L 18,18L 30.25,18L 34.25,22L 25.25,22L 33.25,30L 30,33.25L 22,25.25L 22,34.25L 18,30.25 Z ">
                                <Path.ToolTip>
                                    <ToolTip x:Name="FullWindowToolTip" Content="Развернуть окно" />
                                </Path.ToolTip>
                            </Path>
                        </Grid>

                        <ControlTemplate.Triggers>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter TargetName="FullWindow" Property="Fill" Value="#0094FF" />
                                <Setter TargetName="BorderFull" Property="Opacity" Value="1" />
                            </Trigger>

                            <Trigger Property="IsChecked" Value="True">
                                <Setter Property="Controls:WindowBehaviours.Full" Value="True" />
                                <Setter TargetName="FullWindow" Property="Data" Value="F1 M 54.2499,34L 42,34L 42,21.7501L 45.9999,17.7501L 45.9999,26.7501L 53.9999,18.7501L 57.2499,22.0001L 49.2499,30.0001L 58.2499,30.0001L 54.2499,34 Z M 34,21.7501L 34,34L 21.75,34L 17.75,30.0001L 26.75,30.0001L 18.75,22.0001L 22,18.7501L 30,26.7501L 30,17.7501L 34,21.7501 Z M 21.75,42L 34,42L 34,54.25L 30,58.25L 30,49.25L 22,57.25L 18.75,54L 26.75,46L 17.75,46L 21.75,42 Z M 42,54.25L 42,42L 54.2499,42L 58.2499,46L 49.2499,46.0001L 57.2499,54L 53.9999,57.25L 45.9999,49.25L 45.9999,58.25L 42,54.25 Z " />
                                <Setter TargetName="FullWindowToolTip" Property="Content" Value="Hide in window" />
                            </Trigger>

                            <Trigger Property="IsChecked" Value="False">
                                <Setter Property="Controls:WindowBehaviours.Normal" Value="True" />
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

There is not much to inherit. I suggest you write simple handlers and assign them for button click events. Handlers can be as follows:

    protected void MinimizeClick(object sender, RoutedEventArgs e)
    {
        WindowState = WindowState.Minimized;
    }
    protected void MaximizeClick(object sender, RoutedEventArgs e)
    {
        WindowState = WindowState.Maximized ;
    }

    protected void RestoreClick(object sender, RoutedEventArgs e)
    {
        WindowState = (WindowState == WindowState.Normal) ? WindowState.Maximized :     WindowState.Normal;
    }

    protected void CloseClick(object sender, RoutedEventArgs e)
    {
        Close();
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM