Good XAML Patterns
1:写xaml的时候写在multiply line里(使用Xaml Styler插件会自动转行)。
2:Naming Conventient
- Resources以文件名.key的形式写:InputPageOilSwellResources.DesignNameColumnStyle,若已经在本层的话就不用写文件名了。
- x:Name应该用'_master'的形式,同coding的private
- 命名resources的时候either是style或者Template写成 DesignNameColumnStyle, DesignNameColumnTemplate,中间没有其他的连字符。
- CommonResources的文件名命名
<!-- __________________________ ProjectName_Text_Styles_Library.xaml _________________________________-->
<!-- __________________________ ProjectName_Icon_Library.xaml _________________________________-->
<!-- __________________________ ProjectName_Control_Styles_Library.xaml _________________________________-->
<!-- __________________________ ProjectName_UnitControl_Styles_Library.xaml _________________________________-->
<!-- __________________________ ProjectName_ListControl_Styles_Library.xaml _________________________________--> <!-- ALL FONTS MUST BE EMBEDDED IN THE COMMON "FONTS" FOLDER, AND A BASE FONT STYLE IS CREATED BELOW. IDIVIDUAL STYLES FOR LABELS AND TITLES WILL BE CREATED USING THE "BasedOn" FUNCTION -->
3:选用正确的container:如果需要按钮和textbox并排之间有一个gap,就不要用3列的grid做,应该用stackpanel和空间自身的padding,magging。
4: DataTemplate后面最好有x:Type
<DataTemplate DataType={x:Type string}> <TextBlock Text={Binding}> </DataTemplate> //这里最好加上DataType属性,来指明binding的是什么类型,自己方便。
5: ControlTemplate一定要有TargetType,不然消费这个CT资源会有显示不出结果的问题
<ControlTemplate TargetType = {x:Type ...}> ..... </ControlTemplate> //包括其上面的style也一定要有TargetType
6:所有page都会用到的resources像Fonts都放在高层,如windows层或者App层。
建议放在APP层:Resources defined at the application level can be accessed by all other pages that are part of the application.
<Window> <Style> Fonts定义...... </Style> </Window>
7:区分ContentPresanter 和 ContentControls
ContentControl is the base class for every control that have"content" need to display (example: Button, Label).
ContentPresenter is the placeholder used inside DT or CT by ContentControl to display the content
注意:
ContentControl里有三个属性(Content, Template, ContentTemplate),CT里包含ContentPresenter,用来吧外层的Content属性拿进CT,而ContentPresenter的格式就是ContentTemplate。
Object CT DT
ContentPresenter里只有两个属性(Content, ContentTemplate),没有Template属性,使用在任何Control的DT或者CT内部显示content。
Object DT
//这个从contentpresenter的class定义就可以看出 Class ContentPresenter { public Object Content{get; set;} public DataTemplate ContentTemplate{get; set;} }
如何使用ContentControl(比如Button)的ContentTemplate呢?
<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="WpfApplication4.MainWindow" Title="MainWindow" Height="350" Width="225"> <Window.Resources> <DataTemplate x:Key="ButtonContentTemplate"> <StackPanel Orientation="Horizontal"> <Grid Height="8" Width="8"> <Path HorizontalAlignment="Stretch" Margin="0,0,1.8,1.8" VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FF000000" Data="M0.5,5.7 L0.5,0.5 L5.7,0.5"/> <Path HorizontalAlignment="Stretch" Margin="2,3,0,0" VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FFFFFFFF" Data="M3.2,7.5 L7.5,7.5 L7.5,3.5"/> <Path HorizontalAlignment="Stretch" Margin="1.2,1.4,0.7,0.7" VerticalAlignment="Stretch" Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M2.5,2.5 L7.5,7.5"/> <Path HorizontalAlignment="Stretch" Margin="1.7,2.0,1,1" VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FF000000" Data="M3,7.5 L7.5,7.5 L7.5,3.5"/> <Path HorizontalAlignment="Stretch" Margin="1,1,1,1" VerticalAlignment="Stretch" Stretch="Fill" Stroke="#FFFFFFFF" Data="M1.5,6.5 L1.5,1 L6.5,1.5"/> </Grid> <ContentPresenter Content="{Binding}"/> </StackPanel> </DataTemplate> <ControlTemplate TargetType="Button" x:Key="ButtonControlTemplate"> <Grid> <Ellipse Fill="{TemplateBinding Background}"/> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Grid> </ControlTemplate> </Window.Resources> <StackPanel> <Button Template="{StaticResource ButtonControlTemplate}" Content="1"/> <Button Template="{StaticResource ButtonControlTemplate}" ContentTemplate="{StaticResource ButtonContentTemplate}" Content="2"/> <Button Template="{StaticResource ButtonControlTemplate}" ContentTemplate="{StaticResource ButtonContentTemplate}" Content="3"/> </StackPanel> </Window>
8: PFG2独门秘笈,自定义ContentProperty
Object类可以是任何(Text,Image)
ContentControl workwith ControlTemplate
Property Type Must have type <ControlTemplate TargetType={x:Type Button}>
Content Object
ContentTemplate DataTemplate
Template ControlTemplate
ContentPresenter workwith DataTemplate
Property Type Better have type <DataTemplate DataType={x:Type sys:string}>
Content Object
ContentTemplate DataTemplate
ContentProperty的class定义:
...... public static readonly DependencyProperty TextStyleProperty; [AttachedPropertyBrowsableForType(typeof(FrameworkElement))] public static Style GetTextStyle(DependencyObject d) { return (Style)d.GetValue(TextStyleProperty); } public static void SetTextStyle(DependencyObject d, Style value) { d.SetValue(TextStyleProperty, value); } ...... public static readonly DependencyProperty StyleProperty; [AttachedPropertyBrowsableForType(typeof(FrameworkElement))] public static Style GetStyle(DependencyObject d) { return (Style)d.GetValue(StyleProperty); } public static void SetStyle(DependencyObject d, Style value) { d.SetValue(StyleProperty, value); } ......
注册一个(x:Key="CaretedUnderlined2WrappingTextTemplate")的DataTemplate为某个控件的ContentTemplate属性赋值。
DataTemplate是给控件的ContentTemplatre属性服务的,该DataTemplate下的TextBlock分别被binding到其父的不同属性上(c:ContentProperties.Text 和 c:ContentProperties.Text2)。
<DataTemplate x:Key="CaretedUnderlined2WrappingTextTemplate"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="10"/> <!-- Caret Margin --> <ColumnDefinition Width="*"/> </Grid.ColumnDefinitions> <Image Width="8" HorizontalAlignment="Left" Grid.Column="0" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Source="{Binding Source={StaticResource Icon_ArrowCaretDown}, Converter={StaticResource CaretIconToBrushConverter}}"> <Image.RenderTransform> <TransformGroup> <RotateTransform Angle="-90"/> </TransformGroup> </Image.RenderTransform> </Image> <Rectangle Grid.Column="1" x:Name="BackgroundRect" Style="{TemplateBinding common:ContentProperties.Style}" /> <Canvas Grid.Column="1" VerticalAlignment="Bottom"> <Line X2="{Binding ElementName=BackgroundRect, Path=ActualWidth}" Style="{TemplateBinding common:ContentProperties.Style2}"/> </Canvas> <DockPanel VerticalAlignment="Center" Grid.Column="1" x:Name="DockPanel" > <TextBlock Text="{TemplateBinding common:ContentProperties.Text}" Style="{TemplateBinding common:ContentProperties.TextStyle}" DockPanel.Dock="Left" x:Name="text1"/> <TextBlock Text="{TemplateBinding common:ContentProperties.Text2}" Style="{TemplateBinding common:ContentProperties.TextStyle2}" DockPanel.Dock="Right" TextAlignment="Right"/> </DockPanel> </Grid> </DataTemplate>
创建一个新的style,x:Key="DottedLine2TextBlockWrappingStyle", TargetType="{x:Type ContentControl}",对其间的contentproperties修改。
<Style x:Key="DottedLine2TextBlockWrappingStyle" TargetType="{x:Type ContentControl}"> <Setter Property="ContentTemplate" Value="{StaticResource Underlined2TextTemplate}"/> <Setter Property="common:ContentProperties.Style" Value="{StaticResource UnderlineBlockBackgroundStyle}"/> <Setter Property="common:ContentProperties.Style2" Value="{StaticResource DottedLineStyle}"/> <Setter Property="common:ContentProperties.TextStyle" Value="{StaticResource SmallLightText}"/> <Setter Property="common:ContentProperties.TextStyle2" Value="{StaticResource SmallMedTextWrapping}"/> </Style>
1 <DataTemplate x:Key="CaretedUnderlined2WrappingTextTemplate"> 2 <Grid> 3 <Grid.ColumnDefinitions> 4 <ColumnDefinition Width="10"/> 5 <!-- Caret Margin --> 6 <ColumnDefinition Width="*"/> 7 </Grid.ColumnDefinitions> 8 9 <Image Width="8" HorizontalAlignment="Left" Grid.Column="0" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" 10 Source="{Binding Source={StaticResource Icon_ArrowCaretDown}, Converter={StaticResource CaretIconToBrushConverter}}"> 11 <Image.RenderTransform> 12 <TransformGroup> 13 <RotateTransform Angle="-90"/> 14 </TransformGroup> 15 </Image.RenderTransform> 16 </Image> 17 <Rectangle Grid.Column="1" x:Name="BackgroundRect" Style="{TemplateBinding common:ContentProperties.Style}" /> 18 <Canvas Grid.Column="1" VerticalAlignment="Bottom"> 19 <Line X2="{Binding ElementName=BackgroundRect, Path=ActualWidth}" Style="{TemplateBinding common:ContentProperties.Style2}"/> 20 </Canvas> 21 <DockPanel VerticalAlignment="Center" Grid.Column="1" x:Name="DockPanel" > 22 <TextBlock Text="{TemplateBinding common:ContentProperties.Text}" 23 Style="{TemplateBinding common:ContentProperties.TextStyle}" 24 DockPanel.Dock="Left" x:Name="text1"/> 25 <TextBlock Text="{TemplateBinding common:ContentProperties.Text2}" 26 Style="{TemplateBinding common:ContentProperties.TextStyle2}" 27 DockPanel.Dock="Right" TextAlignment="Right"/> 28 </DockPanel> 29 </Grid> 30 </DataTemplate>
注意<Setter Property="common:ContentProperties.Style" Value="{StaticResource UnderlineBlockBackgroundStyle}"/>的reources在某个地方有定义
下面注册一个style,用来加载到一个控件的ContentTemplate,并且BasedOn="{StaticResource DottedLine2TextBlockWrappingStyle}
<Style x:Key="CaretedDottedLine2TextBlockWrappingStyle" TargetType="{x:Type ContentControl}" BasedOn="{StaticResource DottedLine2TextBlockWrappingStyle}"> <Setter Property="ContentTemplate" Value="{StaticResource CaretedUnderlined2WrappingTextTemplate}"/> </Style>
<Style x:Key="DottedLine2TextBlockWrappingStyle" TargetType="{x:Type ContentControl}"> <Setter Property="ContentTemplate" Value="{StaticResource Underlined2TextTemplate}"/> <Setter Property="common:ContentProperties.Style" Value="{StaticResource UnderlineBlockBackgroundStyle}"/> <Setter Property="common:ContentProperties.Style2" Value="{StaticResource DottedLineStyle}"/> <Setter Property="common:ContentProperties.TextStyle" Value="{StaticResource SmallLightText}"/> <Setter Property="common:ContentProperties.TextStyle2" Value="{StaticResource SmallMedTextWrapping}"/> </Style>
在某一个地方可以使用这个ContentTemplate了
<StackPanel Grid.Column="1" Grid.Row="4" VerticalAlignment="Top"> <ContentControl Style="{StaticResource CaretedDottedLine2TextBlockWrappingStyle}" c:ContentProperties.Text="Customer or customer's agent (please print):" c:ContentProperties.Text2="{Binding Data.CusOrCusAgentPrint}"/> <ContentControl Style="{StaticResource CaretedDottedLine2TextBlockWrappingStyle}" c:ContentProperties.Text="Customer or customer's agent (signature):" c:ContentProperties.Text2="{Binding Data.CusOrCusAgentSignature}"/> </StackPanel>
8:Half Design Pattern: 如果control与control之间如果需要10margin的空间,我们可以给每个control左右各5的margin. 最外面的Container也给5的margin,这样所有的control之间和与最外面的界面边框之间都是10个margin
9: Extension Container Pattern:如果要Grid里要加入更多的control时我们又不希望重新分配grid的列或者行,我们可以把之前某一行/列包含在一个statckpanel里,以便所以增减项目。
10. Leaf Margin Pattern:给margin的时候放在做末尾。