WPF下的RibbonApplicationMenu控件自定义

.Net Framework 4.5和.Net Core开始提供类似Office界面风格的控件。没事想抄个Windows自带的画图玩玩,Ribbon窗口往一套,倒也简单,只是细节方面有些不同,最明显的就是主菜单部分,画图里是扁平的形状,并且内容是用的文本。然而RibbonApplicationMenu去没有提供这样的选项,只能使用图片,而且没有地方可以设置。如果想做得跟画图一样,那就要定制这个菜单了。好在Xaml的机制下可以比较灵活地修改内容模板。以下就说说修改的过程。

定制WPF控件有两种方法,一种是通过继承,另一种是就是新建内容模板。前一种一般是要增加控件的新功能,后一种只是为了修改显式样式。这里只是为了修改显示样式,所以选择后一种就行了。

开始之前,先了解一下Ribbon窗口的结构。

Ribbon

从图中可以看出,这是一个复合控件。如果是简单控件,直接重给控件内容就行了,比如自定义一个圆形按钮,

<ControlTemplate x:Key="roundbutton" TargetType="Button">
    <Grid>
        <Ellipse x:Name="backgroundElement" Fill="{TemplateBinding Background}" Stroke="{TemplateBinding Foreground}" />
        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>
</ControlTemplate>

但如果重绘一个复合控件,只是这么简单的绘制的话,会发现控件不可用了,比如一个ComboBox控件,它实际上包含一个Textbox、一个ToggleButton、一个弹出窗口以及菜单项的模板。这些子控件称为Parts,每个part有一个名称,在呈现控件树的时候使用。

ComboBox 有两个part
PART_EditableTextBox ComboBox的文本内容.
PART_Popup Popup 下拉弹出窗口.

同样,RibbonApplicationMenu也有5个part,分别是
PART_PopupToggleButton 默认按扭,类型为RibbonToggleButton
PART_Popup 下拉框,类型为Popup
PART_SubmenuPlaceholder 子菜单容器,类型为一个容器,比如StackPanel
PART_FooterPaneContentPresenter 底部内容,类型为ContentPresenter
PART_AuxiliaryPaneContentPresenter 右侧内容,类型为ContentPresenter

我们定义这个按钮:

<RibbonToggleButton x:Name="PART_ToggleButton" ClickMode="Release" Label="文件" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Foreground="White" Background="#FF3E3EC7" Focusable="False" IsTabStop="False" FocusedBackground="#FF6161F7" CornerRadius="0,0,0,0" MouseOverBackground="#FF6161F7" MouseOverBorderBrush="#FF6161F7"/>

这里需要注意的两个属性,一个是ClickMode,要设置成Release,否则因为绑定的原因不能正常触发,将CornerRadius设置成"0,0,0,0",默认是“2,2,2,2”。

有了按钮后,还只能触发IsDropDownOpen属性的变化,接下来就要根据这个属性来触发弹框了。我们要定义一个Popup.

<Popup x:Name="PART_Popup" IsOpen="{TemplateBinding IsDropDownOpen}" PopupAnimation="Slide" Placement="Relative">
</Popup>

有了这个Popup,点击蓝色的按钮就看一个弹出的小框框。接下来完善一下其它部分的内容:

<Popup x:Name="PART_Popup" IsOpen="{TemplateBinding IsDropDownOpen}" PopupAnimation="Slide" Placement="Relative" Width="450">
                                    <Border Background="#FFE6E6E6" BorderBrush="#FF5EADCB" BorderThickness="1,1,1,1">
                                        <Grid MinWidth="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxHeight}">
                                            <Grid.RowDefinitions>
                                                <RowDefinition/>
                                                <RowDefinition/>
                                                <RowDefinition/>
                                            </Grid.RowDefinitions>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition/>
                                                <ColumnDefinition/>
                                            </Grid.ColumnDefinitions>
                                            <Border Grid.Row="1" Width="150">
                                                <StackPanel  IsItemsHost="True"/>
                                            </Border>
                                            <Border Grid.Row="1" Grid.Column="1" BorderBrush="Gray" Width="150">
                                                <ContentPresenter x:Name="PART_AuxiliaryPaneContentPresenter"  ContentTemplateSelector="{TemplateBinding AuxiliaryPaneContentTemplateSelector}" Content="{TemplateBinding AuxiliaryPaneContent}" ContentTemplate="{TemplateBinding AuxiliaryPaneContentTemplate}"/>
                                            </Border>
                                            <Border Grid.Row="2" Grid.ColumnSpan="2" Height="30">
                                                <ContentPresenter x:Name="PART_FooterPaneContentPresenter"  Content="{TemplateBinding FooterPaneContent}" ContentTemplate="{TemplateBinding FooterPaneContentTemplate}" ContentTemplateSelector="{TemplateBinding FooterPaneContentTemplateSelector}"/>
                                            </Border>
                                            <RibbonToggleButton x:Name="PART_PopupToggleButton" ClickMode="Release" Label="文件" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Foreground="White" Background="#FF3E3EC7" Focusable="False" IsTabStop="False" IsHitTestVisible="True" HorizontalAlignment="Left" VerticalAlignment="Center" Height="{Binding ActualHeight, ElementName=PART_ToggleButton, Mode=OneWay}" Width="{Binding ActualWidth, ElementName=PART_ToggleButton, Mode=OneWay}" FocusedBackground="#FF6161F7" CornerRadius="0,0,0,0" MouseOverBackground="#FF6161F7" MouseOverBorderBrush="#FF6161F7" />

                                        </Grid>
                                    </Border>
                                </Popup>

这个代码中多了一个RibbonToggleButton,画图程序菜单里有这么一个按钮,这个也是RibbonApplicationMenu的一个Part,实际是继承了RibbonMenuButton的内容,画图里将这个按钮显示在了最上方,如果没这个按钮,主菜单按钮会被挡在下边,为了保持外观的一至性,在弹出框再放一个相同的按钮。同样的,Windows资源管理器也是相同的设计。

整个模板的实现代码如下:

<ControlTemplate TargetType="RibbonApplicationMenu">
                            <Grid>
                                <Popup x:Name="PART_Popup" IsOpen="{TemplateBinding IsDropDownOpen}" PopupAnimation="Slide" Placement="Relative" Width="450">
                                    <Border Background="#FFE6E6E6" BorderBrush="#FF5EADCB" BorderThickness="1,1,1,1">
                                        <Grid MinWidth="{TemplateBinding ActualWidth}" MaxHeight="{TemplateBinding MaxHeight}">
                                            <Grid.RowDefinitions>
                                                <RowDefinition/>
                                                <RowDefinition/>
                                                <RowDefinition/>
                                            </Grid.RowDefinitions>
                                            <Grid.ColumnDefinitions>
                                                <ColumnDefinition/>
                                                <ColumnDefinition/>
                                            </Grid.ColumnDefinitions>
                                            <Border Grid.Row="1" Width="150">
                                                <StackPanel  IsItemsHost="True"/>
                                            </Border>
                                            <Border Grid.Row="1" Grid.Column="1" BorderBrush="Gray" Width="150">
                                                <ContentPresenter x:Name="PART_AuxiliaryPaneContentPresenter"  ContentTemplateSelector="{TemplateBinding AuxiliaryPaneContentTemplateSelector}" Content="{TemplateBinding AuxiliaryPaneContent}" ContentTemplate="{TemplateBinding AuxiliaryPaneContentTemplate}"/>
                                            </Border>
                                            <Border Grid.Row="2" Grid.ColumnSpan="2" Height="30">
                                                <ContentPresenter x:Name="PART_FooterPaneContentPresenter"  Content="{TemplateBinding FooterPaneContent}" ContentTemplate="{TemplateBinding FooterPaneContentTemplate}" ContentTemplateSelector="{TemplateBinding FooterPaneContentTemplateSelector}"/>
                                            </Border>
                                            <RibbonToggleButton x:Name="PART_PopupToggleButton" ClickMode="Release" Label="文件" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Foreground="White" Background="#FF3E3EC7" Focusable="False" IsTabStop="False" IsHitTestVisible="True" HorizontalAlignment="Left" VerticalAlignment="Center" Height="{Binding ActualHeight, ElementName=PART_ToggleButton, Mode=OneWay}" Width="{Binding ActualWidth, ElementName=PART_ToggleButton, Mode=OneWay}" FocusedBackground="#FF6161F7" CornerRadius="0,0,0,0" MouseOverBackground="#FF6161F7" MouseOverBorderBrush="#FF6161F7" />

                                        </Grid>
                                    </Border>
                                </Popup>
                                <RibbonToggleButton x:Name="PART_ToggleButton" ClickMode="Release" Label="文件" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Foreground="White" Background="#FF3E3EC7" Focusable="False" IsTabStop="False" FocusedBackground="#FF6161F7" CornerRadius="0,0,0,0" MouseOverBackground="#FF6161F7" MouseOverBorderBrush="#FF6161F7"/>


                            </Grid>

                        </ControlTemplate>

猜你喜欢

转载自www.cnblogs.com/icoolno1/p/12824353.html