"Consistency in a user interface is an important trait; there are many facets of consistency,
one of which is the consistent look and feel of controls. For example, all buttons should
look roughly the same – similar colors, the same margins, and so on."html
UI的風格一致性是應用程序應當關注的重要特性。app
「Styles provide a convenient way to group a set of properties (and triggers) under a single
object, and then selectively (or automatically as we'll see later) apply it to elements.」ide
用一個Demo,來總結Style。post
MainWindow.xaml以下:flex
<Window x:Class="CreatingAndUsingStyle.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Styled Calculatot" Height="269" Width="180" ResizeMode="CanMinimize"> <Window.Resources> <Style TargetType="Button" x:Key="numericStyle"> <Setter Property="FontSize" Value="20" /> <Setter Property="Margin" Value="4" /> <Setter Property="Padding" Value="6" /> <Setter Property="Effect"> <Setter.Value> <DropShadowEffect Color="Blue"/> </Setter.Value> </Setter> </Style> <Style TargetType="Button" x:Key="operatorStyle" BasedOn="{StaticResource numericStyle}"> <Setter Property="FontWeight" Value="ExtraBold" /> <Setter Property="Effect"> <Setter.Value> <DropShadowEffect Color="Red" /> </Setter.Value> </Setter> </Style> </Window.Resources> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TextBox Background="Cyan" IsReadOnly="True" Grid.ColumnSpan="4"/> <Button Content="7" Grid.Row="1" Style="{StaticResource numericStyle}"/> <Button Content="8" Grid.Row="1" Grid.Column="1" Style="{StaticResource numericStyle}"/> <Button Content="9" Grid.Row="1" Grid.Column="2" Style="{StaticResource numericStyle}"/> <Button Content="4" Grid.Row="2" Style="{StaticResource numericStyle}"/> <Button Content="5" Grid.Row="2" Grid.Column="1" Style="{StaticResource numericStyle}"/> <Button Content="6" Grid.Row="2" Grid.Column="2" Style="{StaticResource numericStyle}"/> <Button Content="1" Grid.Row="3" Style="{StaticResource numericStyle}"/> <Button Content="2" Grid.Row="3" Grid.Column="1" Style="{StaticResource numericStyle}"/> <Button Content="3" Grid.Row="3" Grid.Column="2" Style="{StaticResource numericStyle}"/> <Button Content="0" Grid.Row="4" Style="{StaticResource numericStyle}"/> <Button Content="=" Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" Style="{StaticResource operatorStyle}"> <Button.Effect> <DropShadowEffect Color="Green" /> </Button.Effect> </Button> <Button Content="+" Grid.Row="4" Grid.Column="3" Style="{StaticResource operatorStyle}"/> <Button Content="-" Grid.Row="3" Grid.Column="3" Style="{StaticResource operatorStyle}"/> <Button Content="X" Grid.Row="2" Grid.Column="3" Style="{StaticResource operatorStyle}"/> <Button Content="/" Grid.Row="1" Grid.Column="3" Style="{StaticResource operatorStyle}"/> </Grid> </Window>
效果以下:
ui
1.「A Style is a container for a bunch of Setter objects (and triggers, as we'll see later). Each
setter indicates which property should have which value; the property must be a dependency
property. The FrameworkElement class exposes a Style property that can be set to such a
Style object. Styles are always built as resources.」this
Setter的Property必須是依賴屬性;url
FrameworkStyle暴露了Style這個屬性;spa
Style通常放在Resources中.3d
2."The TargetType property of a Style is typically set, which makes the Style applicable to
that particular type (this can be any type, even a type of a custom control) and any derived
types."
TargetType="Button" 指定Style應用的類型。
通常,咱們使用Style的時候,咱們都會設置這個(In practice ,TargetType is always specified.),想一想爲何?
3. x:Key="numericStyle" 能夠根據須要進行有或無。
a.當其有的時候,咱們須要對須要 Style="{StaticResource numericStyle}" .
b.其不設置的時候,默認全部TargetType使用此Style。 見2.
4. BasedOn="{StaticResource numericStyle}" 這是Style的繼承。
Style繼承時,能夠修改BaseOn Style的Setter。如operatorStyle的 部分所示。
Style繼承很好用,可是要注意:基Style的修改會影響子style.
5.「An element that uses a style can change a property that is set explicitly by a Style (a local
value), and this is stronger than a Style property setter.」
對於應用了Style的element,咱們能夠設置其屬性值,且這個優先級更高(覆蓋Style設置)。如"="Button的 部分所示。
咱們移除 x:Key="numericStyle"。讓全部Button使用這個style.
MainWindow.xaml修改以下:
<Window x:Class="CreatingAndUsingStyle.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Styled Calculatot" Height="269" Width="180" ResizeMode="CanMinimize"> <Window.Resources> <Style TargetType="Button"> <Setter Property="FontSize" Value="20" /> <Setter Property="Margin" Value="4" /> <Setter Property="Padding" Value="6" /> <Setter Property="Effect"> <Setter.Value> <DropShadowEffect Color="Blue"/> </Setter.Value> </Setter> </Style> <Style TargetType="Button" x:Key="operatorStyle" BasedOn="{StaticResource {x:Type Button}}"> <Setter Property="FontWeight" Value="ExtraBold" /> <Setter Property="Effect"> <Setter.Value> <DropShadowEffect Color="Red" /> </Setter.Value> </Setter> </Style> </Window.Resources> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <TextBox Background="Cyan" IsReadOnly="True" Grid.ColumnSpan="4"/> <Button Content="7" Grid.Row="1" /> <Button Content="8" Grid.Row="1" Grid.Column="1" /> <Button Content="9" Grid.Row="1" Grid.Column="2" /> <Button Content="4" Grid.Row="2" /> <Button Content="5" Grid.Row="2" Grid.Column="1" /> <Button Content="6" Grid.Row="2" Grid.Column="2" /> <Button Content="1" Grid.Row="3" /> <Button Content="2" Grid.Row="3" Grid.Column="1" /> <Button Content="3" Grid.Row="3" Grid.Column="2" /> <Button Content="0" Grid.Row="4" Style="{x:Null}"/> <Button Content="=" Grid.Row="4" Grid.Column="1" Grid.ColumnSpan="2" Style="{StaticResource operatorStyle}"> <Button.Effect> <DropShadowEffect Color="Green" /> </Button.Effect> </Button> <Button Content="+" Grid.Row="4" Grid.Column="3" Style="{StaticResource operatorStyle}"/> <Button Content="-" Grid.Row="3" Grid.Column="3" Style="{StaticResource operatorStyle}"/> <Button Content="X" Grid.Row="2" Grid.Column="3" Style="{StaticResource operatorStyle}"/> <Button Content="/" Grid.Row="1" Grid.Column="3" Style="{StaticResource operatorStyle}"/> </Grid> </Window>
效果以下:
1.「Automatic styles are created as resources without a key. This does not mean there is no key,
because it's still a dictionary. The key becomes the actual type to apply the style to defined by
the TargetType property.」
不爲Style指定x:key,這個Style將應用於全部的x:Tyle element;
沒有指定x:key,不表明其沒有key,其key由x:Tyle定義,就本例而言是{x:Type Button}},從Style繼承中(xaml中綠色高亮代碼),可見一斑。
2.若是,這樣的Style被Set在Window的Resource,則影響這個Window上的全部x:Type類型的element;
若是被set在application's resources,則影響全部window。
3.「The Style is applied to all elements of the target type, but not derived types.
Any element that does not set its style explicitly obtains that style automatically. If an element
wishes to revert to its default style, it can set its Style property to null ( {x:Null} in XAML)
or set its Style to another named style.」
若是,咱們但願某個element不該用這個style,咱們能夠設置它的Style屬性爲其餘style;
若是想讓它保持默認的樣子,咱們能夠設置其Style="{x:Null}",如Button 「0」。
「Automatic styles are a great way to create a consistent look and feel without burdening the
developer (or the designer) with the details of the various visual properties. It can also be
used as a quick way to implement skinning."
在Skin文件夾中添加兩個Resource Dictionary,以下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="TextBox"> <Setter Property="Background" Value="LightBlue" /> <Setter Property="Foreground" Value="Black" /> <Setter Property="BorderThickness" Value="2" /> <Setter Property="BorderBrush" Value="DarkBlue" /> <Style.Triggers> <Trigger Property="IsReadOnly" Value="True"> <Setter Property="Background" Value="Blue" /> </Trigger> </Style.Triggers> </Style> <Style TargetType="Button"> <Setter Property="Background" Value="Cyan" /> </Style> </ResourceDictionary>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="TextBox"> <Setter Property="Background" Value="Violet" /> <Setter Property="Foreground" Value="DarkViolet" /> <Setter Property="BorderThickness" Value="2" /> <Setter Property="BorderBrush" Value="LightPink" /> <Style.Triggers> <Trigger Property="IsReadOnly" Value="True"> <Setter Property="Background" Value="Pink" /> </Trigger> </Style.Triggers> </Style> <Style TargetType="Button"> <Setter Property="Background" Value="Red" /> </Style> </ResourceDictionary>
並設置其Property爲:Content/Aways Copy.
「These settings prevent the default compilation to BAML and also provide the flexibility to
change the skins without recompilation. 」
請參考DebugLZQ前面的博文:WPF整理-二進制資源和內容
MainWindow.xaml,MainWindow.xaml.cs以下:
<Window x:Class="WPFStyleTriggerAndControlTemplate.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="303.719" Width="530.785"> <Grid Margin="0,0,2,0"> <TextBox HorizontalAlignment="Left" Height="23" Margin="10,35,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/> <TextBox HorizontalAlignment="Left" Height="23" Margin="156,35,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/> <TextBox HorizontalAlignment="Left" Height="23" Margin="293,35,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" RenderTransformOrigin="1.577,0.303"/> <Button Content="Button" HorizontalAlignment="Left" Margin="433,35,0,0" VerticalAlignment="Top" Width="75"/> <GroupBox FontSize="28" Header="Select Skin" Margin="75,102,62,0" VerticalAlignment="Top" Height="158"> <StackPanel Orientation="Vertical" HorizontalAlignment="Center"> <RadioButton Content="Normal" Checked="AllRadioButtonChecked"/> <RadioButton Content="Blue Skin" Checked="AllRadioButtonChecked"/> <RadioButton Content="Red Skin" Checked="AllRadioButtonChecked"/> </StackPanel> </GroupBox> </Grid> </Window>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WPFStyleTriggerAndControlTemplate { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void AllRadioButtonChecked(object sender, RoutedEventArgs e) { switch (((RadioButton)sender).Content.ToString()) { case "Blue Skin": ChangeSkin("Skins/BlueSkin.xaml"); break; case "Red Skin": ChangeSkin("Skins/RedSkin.xaml"); break; case "Normal": Application.Current.Resources.MergedDictionaries.Clear(); break; } } void ChangeSkin(string skinRelativeUri) { var si = Application.GetContentStream(new Uri(skinRelativeUri, UriKind.Relative)); var rd = (ResourceDictionary)XamlReader.Load(si.Stream); Application.Current.Resources.MergedDictionaries.Clear(); Application.Current.Resources.MergedDictionaries.Add(rd); } } }
運行效果以下:
"The example shows styles applied to the FrameworkElement.Style property, but this is
not the only property that can accept a Style.
Other examples include the following:"
"FrameworkElement.FocusVisualStyle property: Accepts a Style that affects
the way the focus indicator is rendered when that element has the keyboard focus."
"ItemsControl.ItemContainerStyle property: Accepts a Style that affects the
container element of each data item (for example, ListBoxItem for a ListBox)."
"DataGrid.CellStyle: Accepts a Style that affects the way a cell is rendered.
Similar properties exposed by the DataGrid include ColumnHeaderStyle,
DragIndicatorStyle, DropLocationIndicatorStyle, RowHeaderStyle,
and RowStyle."
ControlTemplate通常有以下2種使用方法
方法1:
<Window.Resources>
<ControlTemplate x:Key="AnimatedExpanderButtonTemp" TargetType="{x:Type ToggleButton}">
Template="{StaticResource RevealExpanderTemp}"
--------------
方法2:
<Style TargetType="{x:Type TabControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid>
-----------------------------
關於DataTemplate請參考DebugLZQ前面的博文:WPF整理-使用 DataTemplate
在實際應用中,這3個通常會同時用到。咱們用一個自定義的最大化/最小化/關閉按鈕等,以下:
通常有2種實現方法,第一種方法以下:
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="362.767" Width="524.468" WindowStyle="None" AllowsTransparency="True" Background="Transparent"> <Window.Resources> <Style TargetType="Button" x:Key="btnStyle1"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid x:Name="grid1" Background="Transparent"> <ContentPresenter Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" RecognizesAccessKey="True"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="grid1" Property="Grid.Background" Value="Red"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <ControlTemplate TargetType="Button" x:Key="btnTemplate1"> <Grid x:Name="grid1" Background="Transparent" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"> <ContentPresenter Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" RecognizesAccessKey="True"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="grid1" Property="Grid.Background" Value="LightBlue"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Window.Resources> <Grid > <Grid.Background> <ImageBrush ImageSource="Button_Icons/background_mainwnd.png"/> </Grid.Background> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Orientation="Horizontal" FlowDirection="RightToLeft"> <Button Style="{StaticResource btnStyle1}" Content="X" Foreground="White" FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Top" Width="23" Height="23" Margin="5,0,5,0"/> <Button Template="{StaticResource btnTemplate1}" Content="口" Foreground="White" FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Top" Width="23" Height="23" Margin="5,0,5,0"/> <Button Template="{StaticResource btnTemplate1}" Content="一" Foreground="White" FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Top" Width="23" Height="23" Margin="5,0,5,0"/> </StackPanel> </Grid> </Window>
效果以下:
這種方法的缺點是,咱們設置的Content比較粗糙~
第二中方法,藉助相關的圖標的png圖片及相應的效果圖片,來設置Content,原理同上
<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window1" Height="362.767" Width="524.468" WindowStyle="None" AllowsTransparency="True" Background="Transparent"> <Window.Resources> <Style TargetType="Button" x:Key="btnStyle1"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid Background="Transparent"> <ContentPresenter x:Name="cp1" Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" RecognizesAccessKey="True"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="cp1" Property="Content"> <Setter.Value> <Image Source="Button_Icons/xm.png"/> </Setter.Value> </Setter> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="Button" x:Key="btnStyle2"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid Background="Transparent"> <ContentPresenter x:Name="cp1" Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" RecognizesAccessKey="True"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="cp1" Property="Content"> <Setter.Value> <Image Source="Button_Icons/mxm.png"/> </Setter.Value> </Setter> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Style TargetType="Button" x:Key="btnStyle3"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Grid Background="Transparent"> <ContentPresenter x:Name="cp1" Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" RecognizesAccessKey="True"/> </Grid> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="cp1" Property="Content"> <Setter.Value> <Image Source="Button_Icons/mim.png"/> </Setter.Value> </Setter> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </Window.Resources> <Grid > <Grid.Background> <ImageBrush ImageSource="Button_Icons/background_mainwnd.png"/> </Grid.Background> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <StackPanel Grid.Row="0" Orientation="Horizontal" FlowDirection="RightToLeft"> <Button Style="{StaticResource btnStyle1}" Foreground="White" FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Top" Width="30" Height="30" > <Button.Content> <Image Source="Button_Icons/xn.png" /> </Button.Content> </Button> <Button Style="{StaticResource btnStyle2}" Foreground="White" FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Top" Width="30" Height="30" > <Button.Content> <Image Source="Button_Icons/mxn.png" /> </Button.Content> </Button> <Button Style="{StaticResource btnStyle3}" Foreground="White" FontSize="20" HorizontalAlignment="Left" VerticalAlignment="Top" Width="30" Height="30" > <Button.Content> <Image Source="Button_Icons/min.png" /> </Button.Content> </Button> </StackPanel> </Grid> </Window>
效果以下:
Style的另外一個很是經常使用的場景是:視圖切換。參考DebugLZQ前面總結DataTemplate的博文中的一個例子:6.DataTemplate的一個很是常見的應用
請關注後續整理~
Wish it helps~