控件概述

程序的本质是“数据+算法”——用户输入原始数据,算法处理原始数据并得到结果数据。程序可以使用LED阵列、格式字符串、图形化用户界面(Graphic User Interface,GUI)将结果数据显示给用户,其中图形化用户界面最方便、直观。

在Windows上实现图形化的界面有多种方法,每种方法又拥有自己的一套开发理念和工具并组成一种方法论,常见的有:

  • Windows APl(Win APl):调用Windows底层绘图函数,使用C语言,最原始也最基础。
  • Microsoft Foundation Class(MFC):使用C++语法将原始的Win32API函数封装成控件类。
  • Visual Component Library(VCL):Delphi和C++Builder使用的与MFC相近的控件类库。
  • Visual Basic+ActiveX控件(VB6):使用组件化的思想把WinAPI封装成UI控件,以期多语言共用。
  • Java Swing/AWT:Java SDK中用于跨平台开发GUI程序的控件类库。
  • Windows Form:.NET平台上进行GUl开发的老牌劲旅,完全组件化但需要.NET运行时支持。
  • Windows Presentation Foundation(WPF):后起之秀,使用全新的数据驱动UI的理念。

可以把上述这些方法论分为四代:

  • WinAPI时代:函数调用+Windows消息处理。
  • 封装时代:使用面向对象理念把WinAPI封装成类;由来自UI的消息驱动程序处理数据。
  • 组件化时代:使用面向组件理念在类的基础上封装成组件;消息被封装成事件,变成事件驱动。
  • WPF时代:在组件化的基础上,使用专门的UI设计语言并引入由数据驱动UI的理念。

注:目前流行使用前端的方式实现GUI,如ElectronNanUI等。

WPF中是数据驱动UI,数据是核心、是主动的;UI从属于数据并表达数据、是被动的。WPF把那些能够展示数据、响应用户操作的UI元素称为控件(Control),控件所展示的数据称之为控件的“数据内容”,控件在响应用户的操作后会执行自己的一些方法或以事件(Event)的形式通知应用程序称之为控件的“行为”或“算法内容”

WPF中的控件是个非常抽象的概念——Control是数据和行为的载体,而无需具有固定的形象,如只要是用来显示一个bool类型值并允许用户通过单击来切换true/false/null的UI元素就是一个CheckBox(关注抽象的数据和行为而不是控件具体的形象)。

日常工作中打交道最多的控件无外乎6类,即:

  • 布局控件:可以容纳多个控件或嵌套其他布局控件,用于在UI上组织和排列控件,如Grid、StackPanel、DockPanel 等控件(共同的父类是Panel)。
  • 内容控件:只能容纳一个其他控件或布局控件作为它的内容,如Window、Button等控件(经常需要借助布局控件来规划其内容,共同父类是ContentControl)。
  • 带标题内容控件:相当于一个内容控件,但可以加一个标题(Header),标题部分亦可容纳一个控件或布局,GroupBox、Tabltem等是这类控件的典型代表(共同父类是HeaderedContentControl)。
  • 条目控件:可以显示一列数据,一般情况下这列数据的类型相同,此类控件包括ListBox、ComboBox等(共同基类是ltemsControl,在显示集合类型数据方面功能非常强大)。
  • 带标题条目控件:相当于一个条目控件加上一个标题显示区,Tree Viewltem、Menultem都属于此类控件(往往用于显示层级关系数据,结点显示在其Header区域,子级结点则显示在其条目控件区域,共同基类是HeaderedltemsControl)。
  • 特殊内容控件:这类控件相对比较独立,比如TextBox容纳的是字符串、TextBlock可以容纳可自由控制格式的文本、Image容纳图片类型数据。

6类控件的派生关系如下图所示:

WPF是构建在.NET Framework上的一个子系统,它也是一个用于开发应用程序的框架(Framework),FrameworkElement的Framework指的就是WPF Framework。而FrameworkElement类在UIElement类的基础上添加了很多专门用于WPF开发的API(比如SetBinding方法),所以从这个类开始才算是进入WPF开发柜架。

WPF的内容模型

根据是否可以装载内容、能够装载什么样的内容,WPF的UI元素可以分为如下类型:

名称 注释
ContentControl 单一内容控件
HeaderedContentControl 带标题的单一内容控件
ltemsControl 以条目集合为内容的控件
HeaderedltemsControl 带标题的以条目集合为内容的控件
Decorator 控件装饰元素
Panel 面板类元素
Adorner 文字点缀元素
Flow Text 流式文本元素
TextBox 文本输入框
TextBlock 静态文字
Shape 图形元素

控件的内容可以直接是数据,也可以是控件。当控件的内容还是控件的时候就形成了控件的嵌套(UI布局时尤为常见),被嵌套的控件称为子级控件,所以WPF的UI会形成一个树形结构。

  • 逻辑树(Logical Tree):不考虑控件内部的组成结构,只观察由控件组成的“树”。
  • 可视元素树(Visual Tree):WPF控件往往是由更基本的控件构成的(控件本身就是一棵树),连控件本身的树也考虑在内,比逻辑树更“繁茂”的树。

控件是内存中的对象,控件的内容也是内存中的对象。控件通过自己的某个属性引用着作为其内容的对象,这个属性称为内容属性(Content Property)。“内容属性”是个统称,具体到每种控件上,内容属性都有自己确切的名字——Content、Child、Items或Children。

控件的内容属性与XAML标签的内容存在一定的对应关系,XAML标签的内容区域专门映射了控件的内容属性,下面从语法和常理来解释一下:

  • 严格按照语法来说,控件有内容属性,在XAML里就应该能够使用Atribute=Value 或者属性标签的形式来为内容赋值,如:
<Button Content="OK"/>
<!--或-->
<Button>
<Button.Content>
<sys:String>OK</sys:String>
</Button.Content>
</Button>
  • 按照常理来说,控件对应到XAML文档里就是标签,控件的内容就应该是标签的内容、子级控件就应该是标签的子级元素(简称标签的元素),标签的内容是夹在起始标签和结束标签间的代码,上面的代码可以写成:
<Button>
<sys:String>OK</sys:String>
</Button>

各类内容模型详解

把符合某类内容模型的UI元素称为一个族,每个族用它们共同基类来命名

ContentControl族

本族元素的特点如下:

  • 均派生自ContentControl类。
  • 它们都是控件(Control)。
  • 内容属性的名称为Content。
  • 只能由单一元素充当其内容

“只能由单一元素充当其内容”以Button为例,Buton只能接受一个元素作为它的Content,需要一个带图标、文字的Button时要先用一个可以包含多个元素的布局控件把图片和文字包装起来,再把这个布局控件作为Buton的内容(控件的内容也可以是控件)。

ContentControl族包含的控件:Button、ButtonBase、CheckBox、ComboBoxItem、ContentControl、Frame、GridViewColumnHeader、GropItem、Label、ListBoxItem、ListViewItem、NavigationWindow、RadioButton、RepeatButton、ScrollViewer、StatusBarItem、ToggleButton、ToolTip、UserControl、Window。

HeaderedContentControl族

本族元素的特点如下:

  • 它们都派生自HeaderedContentControl类,HeaderedContentControl是ContentControl类的派生类。
  • 它们都是控件,用于显示带标题的数据。
  • 除了用于显示主体内容的区域外,控件还具有一个显示标题(Header)的区域。
  • 内容属性为Content和Header。
  • 无论是Content 还是Header都只能容纳一个元素作为其内容。

HeaderedContentControl族包含的控件:Expender、GroupBox、HeaderedContentControl、TabItem。

下面演示一个以图标为Header、以文字为主体内容的GroupBox,代码如下:

<!--GroupBox.Content标签可以省略-->
<GroupBox Margin="10" BorderBrush="SlateBlue">
<GroupBox.Header>
<Image Source="img.jpg" Width="20" Height="20"></Image>
</GroupBox.Header>
<GroupBox.Content>
<TextBlock TextWrapping="WrapWithOverflow" Margin="10" Text="测试内容"></TextBlock>
</GroupBox.Content>
</GroupBox>

ItemsControl族

本族元素的特点如下:

  • 均派生自ItemsControl类。
  • 它们都是控件,用于显示列表化的数据。
  • 内容属性为Items或ItemsSource。
  • 每种ItemsControl都对应有自己的条目容器(Item Container)

本族的包含的控件:Menue、MenuBase、ContextMenu、ComboBox、ItemsControl、ListBox、ListViewe、TabControl、TreeView、Selector、StatusBar,对应的Item Container如下:

ItemsControl名称 对应的Item container
ComboBox ComboBoxItem
ContextMenu MenuItem
ListBox ListBoxItem
ListView ListViewItem
Menu MenuItem
StatusBar StatusBarItem
TabControl TabItem
TreeView TreeViewItem

下面列出属于ItemsControl族元素和其对应的Item Container有ComboBox——ComboBoxItem,ContextMenu——MenuItem,ListBox——ListBoxItem,ListView——ListViewItem,Menu——MenuItem,StatusBar——StatusBarItem,TabControl——TabItem,TreeView——TreeViewItem.

ListBox:在XAML中添加数据

ListBox除了可以显示中规中矩的字符串条目还能够显示更多的元素,如CheckBox、RadioButton、TextBox等,例如下面这段代码:

<!--ListBoxItem标签已省略-->
<ListBox x:Name="listbox" Margin="5">
<CheckBox x:Name="chb1" Content="选择1"/>
<CheckBox x:Name="chb2" Content="选择2"/>
<CheckBox x:Name="chb3" Content="选择3"/>
<CheckBox x:Name="chb4" Content="选择4"/>
<Button x:Name="btn1" Content="按钮1"/>
<Button x:Name="btn2" Content="按钮2"/>
<Button x:Name="btn3" Content="按钮3"/>
</ListBox>

表面看上去是ListBox直接包含了一些CheckBox和Buton,实际上这些CheckBox和Buton的父级容器是ListBoxItem。为按钮添加如下的事件代码查看父容器:

private void btn1_Click(object sender, RoutedEventArgs e)
{
Button btn = (sender) as Button;
DependencyObject level1 = VisualTreeHelper.GetParent(btn);
DependencyObject level2 = VisualTreeHelper.GetParent(level1);
DependencyObject level3 = VisualTreeHelper.GetParent(level2); StringBuilder sbr = new StringBuilder();
sbr.AppendLine("level1:"+level1.GetType().ToString());
sbr.AppendLine("level2:" + level2.GetType().ToString());
sbr.AppendLine("level3:" + level3.GetType().ToString());
MessageBox.Show(sbr.ToString());
}

ListBox:在代码中添加数据

除非列表里的元素自始至终都是固定的才使用这种直接把UI元素作为ItemsControl内容的方法,如日期等。大多数情况下,UI上的列表会用于显示动态的后台数据,此时交给ltemsControl的就是程序逻辑中的数据了。在代码中为ListBox添加数据的代码如下:

<Grid>
<ListBox x:Name="listbox" Margin="5"/>
</Grid>
List<Employee> empList = new List<Employee>()
{
new Employee(){Id = 1, Name ="Tim", Age = 30},
new Employee(){Id = 2, Name="Tom",Age=26},
new Employee(){Id = 3,Name="Guo",Age=26},
new Employee(){Id = 4,Name="Yan",Age=25},
new Employee(){Id = 5,Name="Owen",Age=30},
new Employee(){Id=6,Name="Victor",Age=30 }
}; this.listbox.DisplayMemberPath = "Name";
this.listbox.SelectedValuePath = "Id";
this.listbox.ItemsSource= empList; //Employee类
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
  • DisplayMemberPath:这个属性告诉ListBox显示每条数据的哪个属性,ListBox会去调用这个属性值的ToString()方法,把得到的字符串放入一个TextBlock(最简单的文本控件),然后再按前面说的办法把TextBlock包装进一个ListBoxItem里。
  • SelectedValuePath:这个属性将与其SelectedValue属性配合使用,当调用SelectedValue属性时ListBox先找到选中的Item所对应的数据对象,然后把SelectedValuePath的值当作数据对象的属性名称并把这个属性的值取出来

DisplayMemberPath 和Selected ValuePath 是两个相当简化的属性。DisplayMemberPath只能显示简单的字符串,想用更加复杂的形式显示数据需要使用DataTemplate;SelectedValuePath也只能返回单一的值,如果想进行一些复杂的操作可直接使用ListBox的SelectedItem和SelectedItems属性,这两个属性返回的是数据集合中的对象

HeaderedItemsControl族

本族控件*除了具有ItemsControl的特性外,还具显示标题的能力**。本族元素的特点如下:

  • 均派生自HeaderedItemsControl类。
  • 它们都是控件,用于显示列表化的数据,同时可以显示一个标题。
  • 内容属性为Items、ItemsSource和Header。

本族控件只有3个:MenuItem、TreeViewItem、ToolBar

Decorator族

本族中的元素是在UI上起装饰效果的,本族元素的特点如下:

  • 均派生自Decorator类。
  • 起UI装饰作用。
  • 内容属性为Child。
  • 只能由单一元素充当内容。

本族元素有:ButtonChrome、ClassicBorderDecorator、ListBoxChrome、SystemDropShadowChrome、Border、InkPresenter、BulletDecorator、Viewbox、AdornerDecorator。

可以使用Border元素为一些组织在一起的内容加个边框,使用ViewBox元素让组织在一起的内容能够自由缩放

TextBlock和TextBox

两个控件最主要的功能是显示文本:

  • TextBlock只能显示文本,不能编辑,又称静态文本,可以使用丰富的印刷级的格式控制标记显示专业的排版效果。由于需要操纵格式它的内容属性是Inlines(印刷中的“行”),同时也保留一个名为Text的属性(当简单地显示一个字符串时可以使用)
  • TextBox则允许用户编辑其中的内容,由于不需要太多的格式显示它的内容是简单的字符串,内容属性为Text

TextBlock属于比较底层的控件,因此它的性能要比Label好一些。如果需求只是纯文本的显示,并且不提供Access key的支持,那么TextBlock是个不错的选择。

Shape族元素

Shape族元素(只是简单的视觉元素,不是控件)是专门用来在UI上绘制图形的一类元素,本族元素的特点如下:

  • 均派生自Shape类。
  • 用于2D图形绘制。
  • 无内容属性
  • 使用Fill属性设置填充,使用Stroke属性设置边线

注:该族控件一般较少使用,用于自定义控件外观。

Panel族元素

所有用于UI布局的元素都属于这一族,本族元素的特点如下:

  • 均派生自Panel抽象类
  • 主要功能是控制UI布局。
  • 内容属性为Children
  • 内容可以是多个元素,Panel元素将控制它们的布局。

ItemsControl和Panel元素内容都可以是多个元素,但ItemsControl强调以列表的形式来展现数据而Panel则强调对包含的元素进行布局,所以ItemsControl的内容属性是Items和ItemsSource而Panel的内容属性名为Children。

本族元素有:Canvas、DockPanel、Grid、TabPanel、ToolBarOverflowPanel、StackPanel、ToolBarPanel、UniformGrid、VirtualizingPanel|VirtualizingStackPanel、WrapPanel。

UI布局(Layout)

WPF的布局是依靠各种布局元素实现的。

布局元素

WPF中的布局元素有如下几个:

  • Grid:网格,可以自定义行和列并通过行列的数量、行高和列宽来调整控件的布局,近似于HTML中的Table。
  • StackPanel:栈式面板,可将包含的元素在竖直或水平方向上排成一条直线,移除元素时后面的元素会自动向前移动填充空缺
  • Canvas:画布,内部元素可以使用以像素为单位的绝对坐标进行定位,类似于Windows Form编程的布局方式。
  • DockPanel:泊靠式面板,内部元素可以选择泊靠方向,类似于在Windows Form编程中设置控件的Dock属性
  • WrapPanel:自动折行面板,内部元素在排满一行后能够自动折行,类似于HTML中的流式布局。

Grid

Grid元素会以网格的形式对内容元素们(即它的Children)进行布局。

Grid的特点如下:

  • 可以定义任意数量的行和列,非常灵活。
  • 行的高度和列的宽度可以使用绝对数值、相对比例或自动调整的方式进行精确设定,并可设置最大和最小值。
  • 内部元素可以设置自己的所在的行和列,还可以设置自己纵向跨几行、横向跨几列。
  • 可以设置Children元素的对齐方向。

Grid适用的场合有:

  • UI布局的大框架设计
  • 大量UI元素需要成行或者成列对齐的情况。
  • UI整体尺寸改变时,元素需要保持固有的高度和宽度比例
  • UI后期可能有较大变更或扩展。

定义Grid的行与列

Grid类具有ColumnDefinitions和RowDefinitions两个属性,分别是ColumnDefinition和RowDefinition的集合,表示Grid定义了多少列、多少行。

XAML代码如下:

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
</Grid>

C#代码如下:

//添加列
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition());
//添加行
grid.RowDefinitions.Add(new RowDefinition());
grid.RowDefinitions.Add(new RowDefinition());

行高和列宽的单位

计算机图形设计的标准单位是像素(Pixel),所以Grid的宽度和高度单位就是像素。此外,Grid还接受英寸(Inch)、厘米(Centimeter)和点(Point),如下表所示:

英文名称 中文名称 简写 换算
Pixel 像素 px(默认单位,可省略) 图形基本单位
Inch 英寸 in 1inch=96pixel
Centimeter 厘米 cm 1cm=(96/2.54)pixel
Point pt 1pt=(96/72)pixel

实际使用如下所示:

<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30px"/>
<RowDefinition Height="30"/>
<RowDefinition Height="0.5in"/>
<RowDefinition Height="1cm"/>
<RowDefinition Height="30pt"/>
</Grid.RowDefinitions>
</Grid>
  • 属性的值为double类型
  • 因为像素是默认单位,所以px可以省略
  • 其他单位也会被转换成像素并显示在Grid的边缘处

行高和列宽的取值

对于Grid的行高和列宽,可以设置三类值:

  • 绝对值:double数值加单位后缀(如上例),一经设定就不会再改变,又称固定值,适用于当控件的宽度和高度不需要改变或者使用空行、空列作为控件间隔时
  • 比例值:double数值后加一个星号(“*”),比例值的最终像素数=比例值的数值/所有比例值的数值和*未被占用空间的像素数,当改变容器的尺寸时使用比例值的行高会保持固有比例,行高和列宽的默认形式就是比例值,没有显式指定行高或列宽时默认值就是1*(1*又可以简写为*)
  • 自动值:字符串Auto,行高或列宽的实际值将由行列内控件的高度和宽度决定,控件会把行列“撑”到合适的宽度和高度,行列中没有控件时行高和列宽均为0

为控件指定行和列遵循的规则

  • 行和列都是从0开始计数
  • 指定一个控件在某行,就为这个控件的标签添加Grid.Row=“行编号“这样一个Attribute,若行编号为0(即控件处于首行)则可省略这个Attribute
  • 指定一个控件在某列,就为此控件添加Grid.Column=”列编号”这样的Attribute,若列编号为0则Attribute可以者略不写
  • 控件需要跨多个行或列,请使用Grid.RowSpan=“行数“和Grid.ColumnSpan=“列数“两个Atribute

StackPanel

StackPanel可以把内部元素在纵向或横向上紧凑排列、形成栈式布局,StackPanel适合的场合有:

  • 同类元素需要紧凑排列(如制作菜单或者列表)。
  • 移除其中的元素后能够自动补缺的布局或者动画。

StackPanel使用Orientation、HorizontalAlignment和VerticalAlignment这3个属性来控制内部元素的布局,如下所示:

|属性名称|可取值|描述|

|--|--|--|--|

|Orientation|Horizontal
Vertical|决定内部元素是横向累积还是纵向累积|

|HorizontalAlignment|Left
Center
Right
Stretch|决定内部元素水平方向上的对齐方式|

|VerticalAlignment|Top
Center
Bottom
Stretch|决定内部元素竖直方向上的对齐方式|

Canvas

Canvas译成中文就是“画布”,在Canvas里布局就像在画布上画控件一样。使用Canvas布局与在Windows Form窗体上布局基本上是一样的,只是WPF的控件没有Left和Top等属性,当控件被放置在Canvas里时就会被附加上Canvas.X和Canvas.Y属性

Canvas适用的场合包括:

  • 一经设计基本上不会再有改动的小型布局(如图标)。
  • 艺术性比较强的布局。
  • 需要大量使用横纵坐标进行绝对点定位的布局。
<Canvas>
<TextBlock Text="用户名:" Canvas.Left="12" Canvas.Top="12"/>
<TextBox Height="23" Width="200" BorderBrush="Black" Canvas.Left="66" Canvas.Top="19"/>
<TextBlock Text="密码:" Canvas.Left="12" Canvas.Top="40.72" Height="16" Width="36"/>
<TextBox Height="23" Width="200" BorderBrush="Black" Canvas.Left="66" Canvas.Top="38"/>
<Button Content="确定" Width="80" Height="22" Canvas.Left="100" Canvas.Top="67"/>
<Button Content="清除" Width="80" Height="22" Canvas.Left="186" Canvas.Top="67"/>
</Canvas>

除非你确定这个窗口的布局以后不会改变而且窗体尺寸固定,不然还是用Grid进行布局弹性会更好。

DockPanel

DockPanel内的元素会被附加上DockPanel.Dock这个属性,这个属性的数据类型为Dock枚举(可取Left、Top、Right和Bottom四个值)。根据Dock属性值,DockPanel内的元素会向指定方向累积、切分DockPanel内部的剩余可用空间。

DockPanel还有一个重要属性——bool类型的LastChildFill(默认值是True),当LastChildFill属性的值为True时,DockPanel内最后一个元素的DockPanel.Dock属性值会被忽略,这个元素会把 DockPanel内部所有剩余空间充满

实际使用如下:

<Grid>
<DockPanel>
<TextBox DockPanel.Dock="Top" Height="25" BorderBrush="Black" />
<TextBox DockPanel.Dock="Left" Width="150" BorderBrush="Black"/>
<TextBox BorderBrush="Black"/>
</DockPanel>
</Grid>

WrapPanel

WrapPanel内部采用的是流式布局,使用Orientation属性来控制流延伸的方向,使用HorizontalAlignment和VerticalAlignment 两个属性控制内部控件的对齐。在流延伸的方向上,WrapPanel会排列尽可能多的控件,排不下的控件将会新起一行或一列继续排列。

实际使用如下:

<WrapPanel>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
<Button Width="50" Height="50" Content="OK"/>
</WrapPanel>

总结

形而上者谓之道,形而下者谓之器。WPF的内部机理可以说是WPF的“道”,动手实践写程序可以说是WPF的“器”。

参考资料

WPF控件和布局

控件与布局(WPF)

WPF学习二:TextBlock和Label的区别

WPF之控件布局的更多相关文章

  1. CSharpGL(26)在opengl中实现控件布局/渲染文字

    CSharpGL(26)在opengl中实现控件布局/渲染文字 效果图 如图所示,可以将文字.坐标轴固定在窗口的一角. 下载 CSharpGL已在GitHub开源,欢迎对OpenGL有兴趣的同学加入( ...

  2. 创建 WPF 工具箱控件

    创建 WPF 工具箱控件 WPF (Windows Presentation Framework) 工具箱控件模板允许您创建 WPF 控件,会自动添加到 工具箱 安装扩展的安装. 本主题演示如何使用模 ...

  3. Actipro Ribbon For WPF 界面控件免费下载地址

    Actipro Ribbon可以添加ribbon用户界面到你的程序中,功能包含:ribbon大小调整.程序菜单.QAT.嵌入的多种控件.多种布局选项.按键提示.屏幕提示.WPF命令模式用法.多种样式. ...

  4. WPF常用控件应用demo

    WPF常用控件应用demo 一.Demo 1.Demo截图如下: 2.demo实现过程 总体布局:因放大缩小窗体,控件很根据空间是否足够改变布局,故用WrapPanel布局. <ScrollVi ...

  5. WPF 分页控件 WPF 多线程 BackgroundWorker

    WPF 分页控件 WPF 多线程 BackgroundWorker 大家好,好久没有发表一篇像样的博客了,最近的开发实在头疼,很多东西无从下口,需求没完没了,更要命的是公司的开发从来不走正规流程啊, ...

  6. WPF第三方控件盘点

    WPF统一的编程模型.语言和框架,实现了界面设计人员和开发人员工作可以分离的境界,鉴于WPF强大的优势,且一直是开发者关注的地方,下面和大家分享基于WPF项目开发需要用到的第三方控件,包括业界最受好评 ...

  7. WPF 设置控件阴影后,引发的Y轴位置变化问题

    原文:WPF 设置控件阴影后,引发的Y轴位置变化问题 背景 最近遇到一个动画执行时,文本位置变化的问题.如下图: 如果你仔细看的话,当星星变小时,文本往下降了几个像素. 貌似有点莫名其妙,因为控件之间 ...

  8. [WPF]获取控件间的相对位置

    原文:[WPF]获取控件间的相对位置 [WPF]获取控件间的相对位置                             周银辉 我们知道WPF有着比较灵活的布局方式,关于某个控件的坐标,Canv ...

  9. WPF滑块控件(Slider)的自定义样式

    前言 每次开发滑块控件的样式都要花很久去读样式代码,感觉有点记不牢,所以特此备忘. 自定义滑块样式 首先创建项目,添加Slider控件. 然后获取Slider的Window样式,如下图操作. 然后弹出 ...

  10. WPF默认控件模板的获取和资源词典的使用

    一.获取默认的控件模板 WPF修改控件模板是修改外观最方便的方式,但是会出现不知道原来的控件的模板长什么样,或者想用来参考的,下面分享一下获取某控件默认控件模板的方式(已Button为例): 1.创建 ...

随机推荐

  1. ROS节点通信(二)service和client

    目录 1.说明 2.创建功能包 3.自定义通信数据类型 4.编写代码 5.编译配置 5.1.CMakeLists.txt 5.2.package.xml 6.编译运行 1.说明 ROS的节点通信模式有 ...

  2. 【预定义】C语言预定义代码(宏、条件编译等)内容介绍【最全的保姆级别教程】

    浅谈C语言预定义中的预定义符号,#define,以及符号#,##的相关运用 求个赞求个赞求个赞求个赞 谢谢 先赞后看好习惯 打字不容易,这都是很用心做的,希望得到支持你 大家的点赞和支持对于我来说是一 ...

  3. 小知识:MAC上使用预览功能来减小PDF大小

    工作中有些流程会用到PDF电子扫描件,当身边没有扫描设备时,通常会用手机拍照然后合成PDF. 有一个问题是:合成的PDF文件很大,甚至远大于照片本身大小.比如照片是4M的,合成的PDF文件就基本要30 ...

  4. 大数据技术之DataX

    一.DataX简介 DataX 是阿里巴巴开源的一个异构数据源离线同步工具,致力于实现包括关系型数据库(MySQL.Oracle等).HDFS.Hive.ODPS.HBase.FTP等各种异构数据源之 ...

  5. jvm的简介

    什么是jvm? java虚拟机就是二进制字节码的运行环境.我们可以把jvm看做是运行在不同系统上的一个软件应用的计算机,就比如说我们要打开图片,就得用看图软件,或者我们要对文件进行解压,是不是得用解压 ...

  6. Nand flash基本原理

    Nand flash基本原理       Flash全名叫做Flash Memory,属于非易失性存储设备(Non-volatile Memory Device),与此相对应的是易失性存储设备(Vol ...

  7. 解决邮件客户端QQ Mail及Thunderbird无法登入Outlook的问题

    最近无论是安卓手机的邮件客户端, 或者是 Ubuntu 下的 Thunderbird 都无法登入 Outlook 账号, 原因是需要开启双因素验证. 这个在 Outlook 界面上是不能直接设置的, ...

  8. Python之初级RPG小游戏

    在国外网站上找到一个练习Python的小游戏感觉不错,自己实现了一下. 通过该练习你能学到: 元组 字典 简单定义函数和封装 条件控制语句 游戏说明 以下是3个房间和1个花园: Hall 客厅 有一把 ...

  9. Java并发编程实例--10.使用线程组

    并发API提供的一个有趣功能是可以将多个线程组成一个组. 这样我们就能将这一组线程看做一个单元并且提供改组内线程对象的读取操作.例如 你有一些线程在执行同样的任务并且你想控制他们,不考虑有多少个线程仍 ...

  10. Java开发技巧杂记

    杂记一 创建项目的spring initializr,要求是创建spring boot3.0,且不在支持java8语言,且要求语言大于17,所以创建项目时,无法创建srping2.0项目了:如果要创建 ...