我们通常说的模板是用来参照的,同样在WPF中,模板是用来作为制作控件的参照。

一、认识模板

1.1WPF菜鸟看模板

  前面的记录有提过,控件主要是算法和数据的载体。控件的算法主要体现在可以激发的事件、可以调用的方法、能进行的操作等方面;控件的数据体现为:控件能展示哪些数据。上面两方面终决定了控件,在以前的GUI界面上面,或者是Winform上面,控件的数据和功能耦合的太紧密,如果控件想以不同格式显示数据的话,由于控件的形状基本上都固定了,只有重新去自定义控件,以适合数据的显示格式。在WPF中,就可以让模板出马了,如果你让数据以不同的格式显示,那么直接在数据的外衣——DataTemplate里面定义一些控件,安排好布局,到用的时间,直接给拥有数据的控件穿上衣服,数据控件上面就会参照着我们的模板来显示数据了。当然还有一种情况,我们想让一种控件的显示稍作一点修改,由于传统的控件的主要问题就是耦合性太强,才不易控制,在WPF中,一个控件,可能是多个控件的合体,这样我们就相对更容易控制它。由于控件可以拆分,那么在控件里面添加一个控件或者是对某些控件的属性做些修改,就不需要重新定义控件,只需要定义一个ControlTemlate,然后让其装在Style里面,最后让控件拥有Style——那么控件就会照着ControlTemplate里面的定义来显示。

1.2容易弄乱的几个单词区分

  由于模板系列的单词很相像,很容易弄乱掉,所以我觉得还是很有必要把几个单词做简要的说明。在区分之前,还是先了解一下Style,因为Style与ControlTemplate的联系比较紧密,为了防止思路死锁,在此稍作说明,具体的用法会在后面详细记录。Style是风格,对于一个风格,为了不至于有的控件使用该风格搞成四不像,如你让涛哥天天穿个背心去开会,那还得了,一定是要穿的庄重吧,同样控件也是如此,要定义风格要有适合的类,也即要定义其目标类型,然后根据目标的属性来定义风格的具体内容。下面给出一个简要的风格定义:

<Style x:Key="RoundCornerTextBoxStyle" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
                          Background="{TemplateBinding Background}" CornerRadius="10" SnapsToDevicePixels="true">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

  接着解释一下上面风格的含义:一个风格如果作为资源可以供多个控件使用的话,就可以使用x:key,BaseOn获取或设置为当前样式的基类型中定义的样式,基类型中有定义,目标类型没有定义的话,会使用基类型的样式。TargetType是目标类型,对于简单的Setter可以直接写成<Setter Property="属性值" Value=“对应的属性值”/>对于复杂的可以通过内容标签的写法如: <Setter Property="BorderBrush" Value="Red"/>就是设置笔刷属性为红色,上面的代码中是设置控件的Template属性,为ControlTemplate类型的值,其中TemplateBinding为绑定目标控件的属性,可以说TemplateBinding是控件专用的,其他和Binding保持一致。

稍微了解了Style之后再来看DataTemplate和ControlTemplate,他们是控件属性的类型。具体的如下:

ControlTemplate类的代表:

  • ContentControl类型的Template属性,例如Button为ContentControl类
  • ItemsControl类型的Template属性,例如ListBox为ItemsControl类

关于两种类型的元素具体可以参考控件和布局的记录。

DataTemplate的典型代表:

  • ContentControl类型的ContentTemplate属性
  • ItemsControl类型的ItemTemplate属性
  • Gridview的行中的CellTemplate属性

是不是有点乱了,下面给出一个草图(图1)来表述一下,下面的例子中可能会遇到很多类型名和属性容易混淆的地方,可以回头看一下。

图1

二、数据的外衣DataTemplate

  在实际的UI设计中,可能会经常遇到,把已知的数据,通过一定的格式或者是按照一定的排列显示出来,DataTemplate正是解决这样的问题的模板,然后直接把DataTemplate利用空间的属性穿在身上了,最终控件中的数据就会按照一定的排列显示了,最终上了舞台。下面就通过实例来演示一下DataTemplate,该实例涉及到的内容可能比较多,主要包含绑定、资源、ItemsControl、Converter等的使用,如果不懂的话可以留言给我,好了,先看一下效果如图2:

图2

左边的是一个UserControl(继承与ContentControl),中间的是ListBox(继承与ItemsControl)。当点击ListBox的项时,可以改变左边的颜色。直接上代码了:

<Window x:Class="Chapter_09.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Chapter_09"
Title="MainWindow" Height="350" Width="450">
<Window.Resources>
<local:NoConvertImage x:Key="nci"/>
<!--定义详细模板-->
<DataTemplate x:Key="studentDetail">
<Border BorderBrush="Black" BorderThickness="1" CornerRadius="6">
<StackPanel Margin="5" Orientation="Vertical">
<Image Source="{Binding No,Converter={StaticResource nci}}" Width="250"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name:" FontWeight="Bold" ></TextBlock>
<TextBlock Text="{Binding Name}"></TextBlock>
<TextBlock Text="Gender:" FontWeight="Bold" ></TextBlock>
<TextBlock Text="{Binding Sex}"></TextBlock>
<TextBlock Text="Age:" FontWeight="Bold" ></TextBlock>
<TextBlock Text="{Binding Age}"></TextBlock>
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock Text="No:" FontWeight="Bold" ></TextBlock>
<TextBlock Text="{Binding No}"></TextBlock>
<TextBlock Text="Color:" FontWeight="Bold" ></TextBlock>
<TextBlock Text="{Binding Color}"></TextBlock>
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
<!--定义列表模板-->
<DataTemplate x:Key="studentList">
<Grid Margin="2">
<StackPanel Orientation="Horizontal">
<Image Source="Resources/Images/月饼.png" />
<StackPanel>
<TextBlock Text="{Binding Name}"></TextBlock>
<TextBlock Text="{Binding Color}"></TextBlock>
</StackPanel>
</StackPanel>
</Grid>
</DataTemplate>
</Window.Resources>
<StackPanel Orientation="Horizontal" >
<UserControl ContentTemplate ="{StaticResource studentDetail}" Content="{Binding SelectedItem,ElementName=listBox}"/>
<ListBox x:Name="listBox" ItemTemplate="{StaticResource studentList}"/>
</StackPanel>
</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.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes; namespace Chapter_09
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//绑定ListBox和listViewItem
InitialStudentList();
}
private void InitialStudentList()
{
List <Student> studentList= new List<Student>()
{
new Student(){Name="张飞",Age=53,Color="蓝色",No="1",Sex="男"},
new Student(){Name="貂蝉",Age=53,Color="绿色",No="2",Sex="女"},
new Student(){Name="曹操",Age=53,Color="红色",No="3",Sex="男"},
new Student(){Name="华佗",Age=53,Color="橙色",No="4",Sex="男"},
new Student(){Name="赵云",Age=53,Color="紫色",No="5",Sex="男"}
};
this.listBox.ItemsSource = studentList;
}
} #region Student——学生类
public class Student
{
public string Name { get; set; }
public int Age { get; set; }
public string No { get; set; }
public string Sex { get; set; }
public string Color { get; set; }
}
#endregion #region 把ID转化成Uri形式
public class NoConvertImage : IValueConverter
{
#region IValueConverter 成员 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string uriImg = string.Format(@"/Resources/Images/{0}.png", (string)value);
return new BitmapImage(new Uri(uriImg, UriKind.Relative));
} public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
} #endregion
}
#endregion
}

  相对来说,后台代码都是用的以前的知识,前台XAML代码有几点要记录一下:在此处Datatemplate声明为资源,然后通过ContentTemplate,ItemTemplate属性获取到资源。在上面的例子中还有要注意的地方是:UserControl的Content="{Binding SelectedItem,ElementName=listBox}属性为Object类,所以在此绑定ListBox的选定项作为Content,在通过绑定来获取图片和人物的信息,除此还有一个要注意的,还有个是数据驱动,以前我们使用事件驱动应该是通过选项的id来得到Student实体,然后把实体的信息在详情中显示,经过的步骤比较多,可见数据驱动的好处。

三、控件的外衣——ControlTemplate

  ControlTemplate主要用于改变控件的形状,是对控件已有的形状不满意,通常借助Style来指定目标控件的Template属性来实现。下面我们就来举个例子,来以小见大。该例子是把TextBox的边框改成圆角。本例子要用到Blend工具。

首先在新建的项目主窗体中添加一个TextBox,然后通过编辑模板->编辑副本(如图3)

图3

然后通过出现一个创建Style资源,选择应用程序,以便其他控件也可以使用,如图4。之后发现转到App.xaml文件里面了。

图4

  我们暂且不去看代码的意思,我们先看对象和时间线的截图(图5)模板下面有两个控件,但是具有层次关系,这不是我们以前记录的可视树吗?所以为控件指定ControlTemplate衣服,其实就是来修改可视树上的元素。我们把Style部分的代码改为上面介绍Style时引用的代码:

图5

        <Style x:Key="TextBoxStyle1" BasedOn="{x:Null}" TargetType="{x:Type TextBox}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"
                           Background="{TemplateBinding Background}" CornerRadius="10" SnapsToDevicePixels="true">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

发现现在主窗体的textBox已经变成椭圆形的了。上面的代码只是让Border代替了原来的控件。然后去掉了Style的触发器(后面会记录到)。关于ControlTemplate,重在编辑里面的元素,以及元素的属性。下面看一下效果:

图6

除了上面的两个模板之外还有个是只和ItemsControl有关的PanelTemplate:指定 ItemsPresenter 为 ItemsControl 的项的布局创建的面板.也就是指定一个承载ItemsControl的条目的面板,以便使控件的布局更加灵活。例如,我们平时见到的ListBox控件都是竖着下来的,我们下面演示一个横着排列的,其中就利用到了PanelTemplate。代码和效果如图7:

图7

此功能不是本记录的重点,所以不做过多介绍。

四、DataTeplate的另外几种用法

4.1设置DataTemplate的DataType属性  

  除了为控件指定DataTeplate,还可以不指定DataTemplate。而是在DataTemplate设置DataType属性,类似于 Style 类的 TargetType 属性的属性。 如果将此属性设置为数据类型,但没有指定 x:Key, DataTemplate 自动应用于该类型的数据对象 。下面的例子是自动的使用于ItemsControl的条目:

<Window x:Class="WpfControlTemlate.DataTypeOfDataTemplate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfControlTemlate"
xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
Title="DataTypeOfDataTemplate" Height="300" Width="300">
<Window.Resources>
<!--会自动的根据数据类型来做适合控件的衣服-->
<DataTemplate DataType="{x:Type local:Unit}">
<Grid>
<StackPanel Orientation="Horizontal">
<Grid>
<Rectangle Stroke="Yellow" Fill="Orange" Width="{Binding Price}"/>
<TextBlock Text="{Binding Year}"/>
</Grid>
<TextBlock Text="{Binding Price}"/>
</StackPanel>
</Grid>
</DataTemplate>
<c:ArrayList x:Key="ds">
<local:Unit Year="2011年" Price="100"/>
<local:Unit Year="2010年" Price="120"/>
<local:Unit Year="2012年" Price="140"/>
<local:Unit Year="2013年" Price="160"/>
<local:Unit Year="2014年" Price="180"/>
</c:ArrayList>
</Window.Resources>
<StackPanel>
<ListBox ItemsSource="{StaticResource ds}"/>
<ComboBox ItemsSource="{StaticResource ds}" Margin="5"/>
</StackPanel>
</Window>

其中Unit的代码为:

    public class Unit
{
public int Price { get; set; }
public string Year { get; set; }
}

效果如图8:

图8

4.2DataTemplate对XML的支持

  下面两个例子为两个比较常见的例子(TreeView和Menu),只给出代码和效果图,具体用的时间可以自己去试着修改:

XML
XAML

效果如图9

图9

<?xml version="1.0" encoding="utf-8" ?>
<Data xmlns="">
<Operation Name="文件" Gesture="F">
<Operation Name="新建" Gesture="N">
<Operation Name="项目" Gesture="Control+P"/>
<Operation Name="网站" Gesture="Control+W"/>
<Operation Name="文档" Gesture="Control+D"/>
</Operation>
<Operation Name="保存" Gesture="S"/>
<Operation Name="打印" Gesture="P"/>
<Operation Name="退出" Gesture="X"/>
</Operation>
<Operation Name="编辑" Gresture="E">
<Operation Name="拷贝" Gesture="Control+C"/>
<Operation Name="剪切" Gesture="Control+X"/>
<Operation Name="粘贴" Gesture="Control+V"/>
</Operation>
</Data>

<Window x:Class="WpfControlTemlate.MenuTemplate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MenuTemplate" Height="300" Width="300">
<Window.Resources>
<XmlDataProvider x:Key="ds" Source="MenuList.xml" XPath="Data/Operation"/> <HierarchicalDataTemplate DataType="Operation" ItemsSource="{Binding XPath=Operation}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding XPath=@Name}" Margin="10,0"/>
<TextBlock Text="{Binding XPath=@Gesture}"/>
</StackPanel>
</HierarchicalDataTemplate>
</Window.Resources>
<StackPanel MenuItem.Click="StackPanel_Click">
<Menu ItemsSource="{Binding Source={StaticResource ds}}"/>
</StackPanel>
</Window>

后台代码是添加了单击事件来获取点击的是哪个菜单选项,我们可以根据其选项作出相应的操作。

        private void StackPanel_Click(object sender, RoutedEventArgs e)
{
MenuItem mi = e.OriginalSource as MenuItem;
XmlElement xe = mi.Header as XmlElement;
MessageBox.Show(xe.Attributes["Name"].Value);
}

效果如图10

图10

五、Style

5.1Style的Setter

  前面已经稍微理解了一下Style的概念,下面就来记录一下其用法,Setter是设置器的意思。Style有个Setters标签,里面的值为Setter集合。对应的格式为<Setter Property="属性值" Value=“对应的属性值”/>下面来看个例子:

图11

其中上面的Setters标签可以省略。通过Style来限制TextBox的格式,如果不想使用的话,可以使用Style=“{x:Null}”。当然Style也可以添加在App.xaml文件中。如果想用style的话可以用<TextBox Text="Hello Style" Style="{DynamicResource textBoxStyle}"/>动态资源来套用。

5.2  Style中的基本Trigger

  Trigger,触发器,当某些条件满足的时间会触发一个行为。下面先介绍一下基本trigger。Trigger中也有Property和Value,用来限制条件,除此之外还有Setters,表示满足条件呈现的样式。下面的图为当CheckBox选中是字体呈现Orange颜色和20号字体。

图12

5.3 Style中的MultiTrigger

  这个触发器不能从名字上面理解,该触发器应该是多条件触发器,是属性满足了条件呈现特点的Style。下面例子为CheckBox选中,且Content为123的显示一定的Style。

图13

5.4由数据触发的DataTrigger

  在程序设计中,经常碰到如果客户输入不合法的字符串,要显示文本框为红色,来提醒客户。下面就演示一下具体怎么用:下面的例子为TextBox中的Text长度小于7会让Border保持红色。

<Window x:Class="Style.DataTriggerOfStyle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Style"
Title="DataTriggerOfStyle" Height="300" Width="300">
<Window.Resources>
<local:LongToBoolConverter x:Key="LongToBool"/>
<Style TargetType="TextBox">
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={x:Static RelativeSource.Self},Path=Text.Length,Converter={StaticResource LongToBool}}" Value="false">
<Setter Property="BorderBrush" Value="Red"/>
<Setter Property="BorderThickness" Value="1"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<TextBox Margin="5"/>
<TextBox Margin="5"/>
<TextBox Margin="5"/>
</StackPanel>
</Window>

public class LongToBoolConverter : IValueConverter
{
#region IValueConverter 成员 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
int textLength = (int)value;
return textLength>6?true:false;
} public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
} #endregion
}

效果为图14:

图14

  上面的代码中有个的地方是需要解释一下,绑定中有个的RelativeSource,RelativeSource 通过指定绑定源相对于绑定目标的位置,获取或设置绑定源。上面的意思其实就是绑定源的本身。上面还有个Converter,参数中的value已经是长度了,所以不需要直接转化为int型就可以了。

5.5多数据条件触发的MultiDataTrigger

  和上面的MultiTrigger相比,MultiDataTrigger主要验证数据,MultiTrigger验证属性。

<Window x:Class="Style.MultiDataTriggerOfStyle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MultiDataTriggerOfStyle" Height="300" Width="300">
<Window.Resources>
<Style TargetType="ListBoxItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ID}" Width="60"/>
<TextBlock Text="{Binding Name}" Width="120"/>
<TextBlock Text="{Binding Age}" Width="60"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=ID}" Value="2"/>
<Condition Binding="{Binding Path=Name}" Value="Tom"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="Background" Value="Orange"/>
</MultiDataTrigger.Setters>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<ListBox x:Name="listBoxStudent" Margin="5"/>
</StackPanel>
</Window>

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 Style
{
/// <summary>
/// MultiDataTriggerOfStyle.xaml 的交互逻辑
/// </summary>
public partial class MultiDataTriggerOfStyle : Window
{
public MultiDataTriggerOfStyle()
{
InitializeComponent();
this.listBoxStudent.ItemsSource = new List<Student> { new Student { ID = 1, Name = "Tim", Age = 30 }
, new Student { ID = 2, Name = "Tom", Age = 30 }
, new Student { ID = 3, Name = "lzp", Age = 30 }
, new Student { ID = 4, Name = "haiziguo", Age = 30 }};
}
}
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}

效果如图15:

图15

5.6事件触发的EventTrigger

  该触发器与其他触发器不大一样,他不是属性也不是数据触发Style改变的,而是由事件触发的;被触发后不是执行的Setter,而是执行的一段动画。关于动画不做说明,下面只给出实例。记录完动画的章节,再回来看看。下面的例子是鼠标移到Button控件和离开执行的动画。

<Window x:Class="Style.EventTriggerOfStyle"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="EventTriggerOfStyle" Height="300" Width="300">
<Window.Resources>
<Style TargetType="Button">
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation To="150" Duration="0:0:0:2" Storyboard.TargetProperty="Width"/>
<DoubleAnimation To="150" Duration="0:0:0:2" Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0:2" Storyboard.TargetProperty="Width"/>
<DoubleAnimation Duration="0:0:0:2" Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded"/>
</Window.Triggers>
<Canvas>
<Button Width="40" Height="40" Content="OK"/>
</Canvas>
</Window>

六、总结

  本篇记录主要从DataTemplate和ControlTemplate入手,通过一些小例子来说明了他们的用途。注意区分其使用场合,前者只要是控制数据的显示方式,后者是控制控件的已有形状的改变。除此之外,还介绍了Style,由于其概念简单性,没有做过多的解释,只是给出了几个例子,等用到的时间再进行查阅。不足的地方是:关于ContentPresenter与DataTemplate以及ControlTemplate之间的关系不是太理解,所以本文少了一部分《寻找失落的控件》,如果有比较好的文章或者是比较好的资料帮助理解的,请留言,将不胜感激!本文是读书笔记,里面难免有理解不对的地方,欢迎讨论!最后祝大家节日愉快!下一篇:《深入浅出WPF》笔记——绘图与动画 。

wpf 中的style的更多相关文章

  1. WPF中的Style(风格,样式)(转)

    在WPF中我们可以使用Style来设置控件的某些属性值,并使该设置影响到指定范围内的所有该类控件或影响指定的某一控件,比如说我们想将窗口中的所有按钮都保持某一种风格,那么我们可以设置一个Style,而 ...

  2. WPF中的Style(风格,样式)

    作者: 周银辉  来源: 博客园  发布时间: 2009-02-27 15:04  阅读: 6698 次  推荐: 0   原文链接   [收藏]   在WPF中我们可以使用Style来设置控件的某些 ...

  3. wpf中在style的template寻找ControlTemplate和DataTemplate的控件

    一.WPF中的两棵树 WPF中每个控件的Template都是由ControlTemplate构成,ControlTemplate包含了构成该控件的各种子控件,这些子控件就构成了VisualTree:而 ...

  4. WPF 中的style 样式

    WPF相较于以前学的WinForm,WPF在UI设计与动画方面的炫丽是最吸引我来学习的.在WPF中XMAL代码的引入使得代码的编写能够前后端分离,为获得更好的界面,也使得我们不得不分出一半的时间花在前 ...

  5. WPF中的Style

    一.Style基础知识 构成Style最重要的两种元素是Setter和Trigger Setter类帮助我们设置控件的静态外观风格 Trigger类帮助我们设置控件的行为风格 Setter类的Prop ...

  6. 在WPF中自定义控件(3) CustomControl (上)

    原文:在WPF中自定义控件(3) CustomControl (上) 在WPF中自定义控件(3) CustomControl (上)                              周银辉 ...

  7. [Songqw.Net 基础]WPF插件化中同步Style

    原文:[Songqw.Net 基础]WPF插件化中同步Style 版权声明:本文为博主原创文章,未经博主允许可以随意转载 https://blog.csdn.net/songqingwei1988/a ...

  8. WPF中Style文件的引用——使用xaml代码或者C#代码动态加载

    原文:WPF中Style文件的引用--使用xaml代码或者C#代码动态加载 WPF中控件拥有很多依赖属性(Dependency Property),我们可以通过编写自定义Style文件来控制控件的外观 ...

  9. WPF 中style文件的引用

    原文:WPF 中style文件的引用 总结一下WPF中Style样式的引用方法: 一,内联样式: 直接设置控件的Height.Width.Foreground.HorizontalAlignment. ...

随机推荐

  1. QT从入门到入土(三)——文件的读写操作

     引言 文件的读写是很多应用程序具有的功能,甚至某些应用程序就是围绕着某一种格式文件的处 理而开发的,所以文件读写是应用程序开发的一个基本功能. Qt 提供了两种读写纯文本文件的基本方法: 用 QFi ...

  2. nginx+waf防火墙

    1.官网下载nginx源码包(nginx-1.20.0.tar.gz) 新建nginx安装目录​mkdir -p /opt/nginx​新增nginx运行用户​useradd -s /sbin/nol ...

  3. 备战- Java虚拟机

    备战- Java虚拟机 试问岭南应不好,却道,此心安处是吾乡. 简介:备战- Java虚拟机 一.运行时数据区域 程序计算器.Java 虚拟机栈.本地方法栈.堆.方法区 在Java 运行环境参考链接: ...

  4. deepin修改数据源升级到deepin15.11桌面版

    参考:https://blog.csdn.net/baidu_41751590/article/details/89064220 1,我修改数据源地址: 换成上海交通大学源地址: http://ftp ...

  5. Beam Search快速理解及代码解析(上)

    Beam Search 简单介绍一下在文本生成任务中常用的解码策略Beam Search(集束搜索). 生成式任务相比普通的分类.tagging等NLP任务会复杂不少.在生成的时候,模型的输出是一个时 ...

  6. 微信小程序云开发-云函数-云函数实现数据的查询、修改和删除功能

    一.云函数获取商品信息 1.创建云函数getData,云函数功能:获取商品信息 2.在本地小程序页面调用云函数getData  二.云函数修改商品信息 1.创建云函数updateData,云函数功能: ...

  7. Java-数组有关

    1.复制数组 复制数组主要有三类方法: 1.使用循环语句逐个赋值数组元素 2.使用System类中的静态方法arraycopy 3.使用clone方法复制数组 对于2,详述如下: arraycopy( ...

  8. ThinkPHP3.2.3使用PHPExcel类操作excel导入读取excel

    方法一: 1. 下载PHPExcel并保存在如下位置: 2. 在控制器中引用 vendor("PHPExcel.PHPExcel"); $objReader = \PHPExcel ...

  9. informix数据库分页

    需求描述 当查询结果返回大量数据情况下,比如报表查询.需要按一定条件排序提供分页呈现数据. INFORMIX实现方案:Informix 数据库提供了非常便捷.高效的SQL. SELECT SKIP M ...

  10. HttpRunner3源码阅读: 1. 目录结构分析

    初衷 身处软件测试行业的各位应该都有耳闻HttpRunner 开源测试工具/框架(接口测试),作者博客 为什么出这系列? 不少测试同行都建议阅读HttpRunner,源码学习其设计思想. 社区当下Py ...