zoukankan      html  css  js  c++  java
  • WPF学习(3)布局

    今天我们来说说WPF的布局。我们知道WinForm的布局主要是采用基于坐标的方式,当窗口内容发生变化时,里面的控件不会随之动态调整,这就造成了一个很不好的用户体验。而WPF为了避免这个缺点,采用了基于流的这种灵活的布局方式(WinForm在.net 2.0中也增加了对flow-based的支持)。工欲善其事,必先利其器。首先,我们来看看WPF的布局控件主要有哪些。然后,了解下主要用于构成复杂控件的原始控件。最后说说关于内容溢出的处理办法。

    1.布局控件

     WPF常用的布局控件主要有这么几个:Grid、StackPanel、Canvas、DockPanel、WrapPanel,它们都继承自Panel抽象类。

    1.1Grid

    Grid应该算是WPF中最常用的布局控件了。新建一个窗口可看到Grid是作为其默认的布局控件的。它的效果类似html中的Table,只不过在外观上Grid默认是没有边框的。我们可以在Visual Studio中的Xaml设计器上快速的创建表格,如下图所示:

    通过Xaml设计器设计,会自动为我们生成布局代码,值都是精确的,我们可以适当微调。当然,直接手写Xaml也可以达到同样的效果,下面我们来用C#代码来实现这样的布局:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    
    namespace LayoutDemo
    {
        /// <summary>
        /// GridWnd1.xaml 的交互逻辑
        /// </summary>
        public partial class GridWnd1 : Window
        {
            public GridWnd1()
            {
                InitializeComponent();
                
                Grid grid = new Grid();
                //添加行
                RowDefinition row1 = new RowDefinition();
                row1.Height = new GridLength(1, GridUnitType.Star);
                //添加Button
                Button button1 = new Button();
                button1.Content = "Button1";
                button1.Width = 70;
                button1.Height = 30;
                //button1.SetValue(Grid.RowProperty, 0);
                Grid.SetRow(button1, 0);
                RowDefinition row2 = new RowDefinition();
                row2.Height = new GridLength(1, GridUnitType.Star);
                RowDefinition row3 = new RowDefinition();
                row3.Height = new GridLength(1, GridUnitType.Star);
                grid.RowDefinitions.Add(row1);
                grid.RowDefinitions.Add(row2);
                grid.RowDefinitions.Add(row3);
                //添加列
                ColumnDefinition col1 = new ColumnDefinition();
                col1.Width = new GridLength(1, GridUnitType.Star);
                ColumnDefinition col2 = new ColumnDefinition();
                col2.Width = new GridLength(1, GridUnitType.Star);
                ColumnDefinition col3 = new ColumnDefinition();
                col3.Width = new GridLength(1, GridUnitType.Star);
                grid.ColumnDefinitions.Add(col1);
                grid.ColumnDefinitions.Add(col2);
                grid.ColumnDefinitions.Add(col3);
    
                grid.Background = Brushes.LightBlue;
                grid.Children.Add(button1);
                this.Content = grid;
            }
        }
    }
    View Code

     上面代码中,在设置Grid的行高列宽时使用的是“*”,这就要我们了解下宽带和高度可以有哪些值。先来说下它们的单位:

    像素是默认单位,当使用其它三种时也会自动转换为像素。

    对于Grid的行高和列宽我们可以设置三种值:

      1.绝对值: double类型的值加单位,单位可以有上图几种,省略不写默认为px,不会随着容器的改变而改变

      2.比例值 :double类型的值加星号“*”,当是“1*”时,“1”可以省略,计算的是在所有比例值中所占的比例,会动态调整

      3.自动值 :字符串“Auto”,它会根据实际的高度或者宽度来自动调整

    注意:在WPF也有一个Table类,它是用来文档显示,而此处的Grid是用来界面显示的。

    1.2StackPanel

     StackPanel正如它的名字一样,默认的情况下,它的子元素会从上到下排列,当然我们可以控制它的Orientation属性控制排列方向。Orientation属性有两个值一个Horizontal,一个是Vertical(默认)。看下图:

    StackPanel还有一个FlowDirection,它一般结合Orientation的值为Horizontal来使用,用来控制元素在水平方向上的排列方式。上图的Xaml代码:

    <Window x:Class="LayoutDemo.StackPanel1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="StackPanel1" Height="267" Width="334">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
            <StackPanel>
                <Button Content="button1" />
                <Button Content="button2" />
            </StackPanel>
            <StackPanel Orientation="Horizontal" Grid.Column="1">
                <Button Content="button1" />
                <Button Content="button2" />
            </StackPanel>
            <StackPanel Orientation="Horizontal" Grid.Column="2" FlowDirection="RightToLeft">
                <Button Content="button1" />
                <Button Content="button2" />
            </StackPanel>
        </Grid>
    </Window>
    View Code

    1.3Canvas

     Canvas相对于其它的布局控件来说,是有点儿特殊的,其它布局控件基本上都是基于流的,而它是基于坐标的。

    Canvas有四个用于定位的附加属性Left、Top、Right和Bottom,分别水平方向(X轴)两个,竖直方向(Y轴)两个。

    需要注意的一点是:当在一个方向同时设置了两个附加属性时,Left会覆盖Right,Top会覆盖Bottom。这样,排列组合可以有四种方式。还有一个zindex来控制Z轴,在Sliverlight中作为了Canvas的附加属性(Canvas.zindex),而在WPF中作为了Panel的附加属性(Panel.zindex)。如下图所示:

    默认情况下,后面的元素会盖住前面的元素,也就是button2会盖住button1,通过修改Panel.zindex的值来控制谁显示在前面。

    1.4DockPanel

    DockPanel可以让元素停靠在面板的某一边,然后拉伸元素以填满全部的宽度或高度。它有一个Dock属性用来设置停靠的位置,有Left、Top、Right和Bottom四个值。先来看下效果:

    需要注意的是,DockPanel没有Fill属性,但是默认情况会将最后的子元素用来填充剩余空间,除非将其LastChildFill设为False,如下图所示:

    与StackPanel一样,任何元素的拉伸都是有其Horizontal或者Vertical属性为Stretch造成,当设置为其它时又是又一番样子,请看下图:

    Xaml代码如下:

    <Window x:Class="LayoutDemo.DockPanel1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="DockPanel1" Height="300" Width="300">
        <Grid>
            <DockPanel LastChildFill="False">
                <Button Content="button1" DockPanel.Dock="Top" Background="Red" HorizontalAlignment="Center" />
                <Button Content="button2" DockPanel.Dock="Left" Background="Green" VerticalAlignment="Center" />
                <Button Content="button3" DockPanel.Dock="Right" Background="Blue" VerticalContentAlignment="Center"/>
                <Button Content="button4" DockPanel.Dock="Bottom" Background="BlanchedAlmond"/>
                <Button Background="Silver" Content="button5" />
            </DockPanel>
        </Grid>
    </Window>
    View Code

     其实仔细说来,DockPanel的功能要比StackPanel要强。当我们把DockPanel的LastChildFill设为False时,可以实现像StackPanel一样的布局。

    先看图:

    Xaml代码:

    <Window x:Class="LayoutDemo.DockPanel2"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="DockPanel2" Height="300" Width="300">
        <Grid>
            <DockPanel LastChildFill="False">
                <Button Content="button1" DockPanel.Dock="Top" />
                <Button Content="button2" DockPanel.Dock="Top" />
                <Button Content="button3" DockPanel.Dock="Top" />
            </DockPanel>
        </Grid>
    </Window>
    View Code

    1.5WrapPanel

     WrapPanel在可能的空间中,一次以一行或者一列的形式布置控件元素。与StackPanel类似,WrapPanel也有Orientation属性来控制布局方向,不过它默认值是Horizontal(StackPanel默认是Vertical)。

    当你为一行或一列中的第一个元素设置高度或宽度时,该行或该列的高度或宽度默认也设为该值,这是由元素的Horizontal和Vertical的值默认为Stretch导致的。我们可以认为来修改,如下图所示:

    当你在伸缩窗口时,元素会自动调整。

    Xaml代码:

    <Window x:Class="LayoutDemo.WrapPanel1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="WrapPanel1" Height="300" Width="300">
        <Grid>
            <WrapPanel Orientation="Horizontal" >
                <Button Content="button1" Height="60"/>
                <Button Content="button2" Height="40"/>
                <Button Content="button3" VerticalAlignment="Top"/>
                <Button Content="button4" VerticalAlignment="Bottom"/>
                <Button Content="button5" />
                <Button Content="button6" />
            </WrapPanel>
        </Grid>
    </Window>
    View Code

     WrapPanel也有和StackPanel一样的FlowDirection属性,功能一样,不在赘述。

    2.原始面板

    这里说的原始面板是指大部分位于System.Windows.Controls.Primitives 命名空间下的布局控件,主要有这么几个TabPanel、ToolBarOverFlowPanel、UniformGrid,还有一个ToolBarTray是位于System.Windows.Controls命名空间的,它们主要用于构成其他更复杂控件的一部分的基类和控件。关于该命名空间,可查看MSDN 。本节和模板Template联系紧密,我们将在模板时细说。这里以TabPanel为例,简单说明下。由于TabPanel是构成TabControl的内部的默认的布局控件,所以我们需要用Blend解剖TabControl来看下它的模板:

    <SolidColorBrush x:Key="TabControlNormalBorderBrush" Color="#8C8E94"/>
            <Style x:Key="TabControlStyle1" TargetType="{x:Type TabControl}">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                <Setter Property="Padding" Value="4,4,4,4"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/>
                <Setter Property="Background" Value="#F9F9F9"/>
                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TabControl}">
                            <Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition x:Name="ColumnDefinition0"/>
                                    <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
                                    <RowDefinition x:Name="RowDefinition1" Height="*"/>
                                </Grid.RowDefinitions>
                                <TabPanel x:Name="HeaderPanel" Grid.Column="0" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
                                <Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
                                    <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                </Border>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="TabStripPlacement" Value="Bottom">
                                    <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
                                    <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                    <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                    <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
                                    <Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
                                </Trigger>
                                <Trigger Property="TabStripPlacement" Value="Left">
                                    <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                                    <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                    <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
                                    <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
                                    <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
                                    <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
                                    <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                    <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                                    <Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
                                </Trigger>
                                <Trigger Property="TabStripPlacement" Value="Right">
                                    <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                                    <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                    <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
                                    <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
                                    <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
                                    <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
                                    <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                    <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                                    <Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
    View Code

    我们发现TabControl主要是由Header和Content部分构成的,Header就是由我们这里的TabPanel来充当的,而Content则由ContentPresenter来充当。知道了这些,我们可以做一个另类的TabControl了,看下效果图:

    Xaml代码:

    <Window
            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" mc:Ignorable="d" x:Class="LayoutDemo.TabPanel1"
            Title="TabPanel1" Height="300" Width="300">
        <Window.Resources>
            <SolidColorBrush x:Key="TabControlNormalBorderBrush" Color="#8C8E94"/>
            <Style x:Key="TabControlStyle1" TargetType="{x:Type TabControl}">
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                <Setter Property="Padding" Value="4,4,4,4"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/>
                <Setter Property="Background" Value="#F9F9F9"/>
                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type TabControl}">
                            <Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition x:Name="ColumnDefinition0"/>
                                    <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
                                </Grid.ColumnDefinitions>
                                <Grid.RowDefinitions>
                                    <RowDefinition x:Name="RowDefinition0" Height="*"/>
                                    <RowDefinition x:Name="RowDefinition1" Height="Auto"/>
                                </Grid.RowDefinitions>
                                <Border x:Name="ContentPanel"  BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="0" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
                                    <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                </Border>
                                <StackPanel x:Name="HeaderPanel" Orientation="Horizontal" Grid.Column="0" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="1" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1" HorizontalAlignment="Right"/>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="TabStripPlacement" Value="Bottom">
                                    <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
                                    <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                    <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                    <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
                                    <Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
                                </Trigger>
                                <Trigger Property="TabStripPlacement" Value="Left">
                                    <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                                    <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                    <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
                                    <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
                                    <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
                                    <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
                                    <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                    <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                                    <Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
                                </Trigger>
                                <Trigger Property="TabStripPlacement" Value="Right">
                                    <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                                    <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                                    <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
                                    <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
                                    <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
                                    <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
                                    <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                                    <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                                    <Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Resources>
        <Grid>
            <TabControl Style="{DynamicResource TabControlStyle1}">
                <TabItem Header="Tab1">
                    <TextBlock Text="Hello" />        
                </TabItem>
                <TabItem Header="Tab2">
                    <TextBlock Text="WPF" />
                </TabItem>      
            </TabControl>
        </Grid>
    </Window>
    View Code

     这里只是简单改了布局,用StackPanel来简单替换了TabPanel,当然根据需要,也可以用其它的布局控件来替换了。

    3.内容溢出

    内建的面板会尽可能的满足其子元素的尺寸要求,然而有时候,我们不能不压缩子元素的尺寸,这样导致子元素的内容溢出。处理内容溢出主要有以下几种方式:

    3.1剪辑(Clipping)

    通过设置ClipToBounds属性来控制是否让元素超出边界部分在外边界显示。尽管这个属性是所有UIElement及其子类都有的属性,但是只对Canvas起作用,其它布局控件都会剪辑掉超出             部分。当然,ClipToBounds属性也可以对自己内容进行剪辑。举个例子说明:

    这是当我们MouseOver的时候Button的样子,此时ClipToBounds默认为False,我们将它改为True然后再MouseOver到Button上看下效果:

    发现溢出部分被剪辑掉了。Xaml代码如下:

    <Window
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:Microsoft_Windows_Themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="LayoutDemo.ContentOverflow"
            Title="ContentOverflow" Height="300" Width="300">
        <Window.Resources>
            <LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0">
                <GradientStop Color="#F3F3F3" Offset="0"/>
                <GradientStop Color="#EBEBEB" Offset="0.5"/>
                <GradientStop Color="#DDDDDD" Offset="0.5"/>
                <GradientStop Color="#CDCDCD" Offset="1"/>
            </LinearGradientBrush>
            <SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/>
            <Style x:Key="ButtonStyle1" TargetType="{x:Type Button}">
                <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/>
                <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
                <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
                <Setter Property="HorizontalContentAlignment" Value="Center"/>
                <Setter Property="VerticalContentAlignment" Value="Center"/>
                <Setter Property="Padding" Value="1"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type Button}">
                            <Microsoft_Windows_Themes:ButtonChrome x:Name="Chrome" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" RenderDefaulted="{TemplateBinding IsDefaulted}" SnapsToDevicePixels="true">
                                <ContentPresenter x:Name="cp" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RenderTransformOrigin="0.5,0.5">
                                    <ContentPresenter.RenderTransform>
                                        <TransformGroup>
                                            <ScaleTransform/>
                                            <SkewTransform/>
                                            <RotateTransform/>
                                            <TranslateTransform/>
                                        </TransformGroup>
                                    </ContentPresenter.RenderTransform>
                                </ContentPresenter>
                            </Microsoft_Windows_Themes:ButtonChrome>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsKeyboardFocused" Value="true">
                                    <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="true">
                                    <Setter Property="RenderTransform" TargetName="cp">
                                        <Setter.Value>
                                            <TransformGroup>
                                                <ScaleTransform ScaleX="1.5" ScaleY="1.5"/>
                                                <SkewTransform/>
                                                <RotateTransform/>
                                                <TranslateTransform/>
                                            </TransformGroup>
                                        </Setter.Value>
                                    </Setter>
                                </Trigger>
                                <Trigger Property="ToggleButton.IsChecked" Value="true">
                                    <Setter Property="RenderPressed" TargetName="Chrome" Value="true"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="false">
                                    <Setter Property="Foreground" Value="#ADADAD"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Resources>
        <Grid>
            <Button Content="button" HorizontalAlignment="Center" VerticalAlignment="Center" Style="{DynamicResource ButtonStyle1}" ClipToBounds="True" />
        </Grid>
    </Window>
    View Code

     这里需要注意的一点是:剪辑是在RenderTransform生效之前发生的。

    3.2滚屏(Scrolling)

    主要是通过ScrollViewer控件来实现的,属性主要有HorizontalScrollBarVisibility(默认值为auto)和VerticalScrollBarVisibility(默认为Visible)。直接看例子:

    <Window x:Class="LayoutDemo.ContentOverflow1"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="ContentOverflow1" Height="300" Width="300">
        <Grid>
            <ScrollViewer HorizontalScrollBarVisibility="Visible">
                <StackPanel Orientation="Horizontal">
                    <Button Content="button1" Width="100" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top"/>
                    <Button Content="button1" Width="100" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top"/>
                    <Button Content="button1" Width="100" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top"/>
                    <Button Content="button1" Width="100" Height="100" HorizontalAlignment="Left" VerticalAlignment="Top"/>
                </StackPanel>
            </ScrollViewer>
        </Grid>
    </Window>
    View Code

     效果图如下:

     3.3缩放(scalling)

    说到缩放,我们首先会想到ScaleTransform,它是相对于元素的自身大小来进行缩放,相对于滚屏方式,需要写很多额外的代码,有没有和ScrollViewer一样使用简单的控件来实现缩放的效果呢?有,那就是Viewbox,那是一种类似于只有一个子元素的面板,是一种Decorator装饰类,通过它的Stretch属性来实现任意内容的缩放。假如我们在一个300*300的窗口有一个300*400的大号按钮,窗口只能显示其中的的一部分,现在我们可以用Viewbox来缩放让它完全显示在窗口上面,先看原图:

    再看使用Viewbox,设置其Stetch属性后的效果:

    经过缩放后,已经能够完全显示了。Xaml代码如下:

    <Window x:Class="LayoutDemo.ContentOverflow2"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="ContentOverflow2" Height="300" Width="300">
        <Viewbox Stretch="Uniform" StretchDirection="Both">
            <Button Content="button1" Width="400" Height="300" />
        </Viewbox>
    </Window>
    View Code

     4.总结

    WPF布局牵涉的内容很多,只有在平时不断积累才能渐趋完善!

  • 相关阅读:
    tuple 元组及字典dict
    day 49 css属性补充浮动 属性定位 抽屉作业
    day48 选择器(基本、层级 、属性) css属性
    day47 列表 表单 css初识
    day 46 http和html
    day 45索引
    day 44 练习题讲解 多表查询
    day 40 多表查询 子查询
    day39 表之间的关联关系、 补充 表操作总结 where 、group by、
    day38 数据类型 约束条件
  • 原文地址:https://www.cnblogs.com/jellochen/p/3416600.html
Copyright © 2011-2022 走看看