前言

总目录
在上一章中,初步的认识了WPF,那么这一章将逐个的认识一些常用的控件以及这些控件的常用属性,这对于我们我们后续开发WPF程序是非常有必要的。


一、Window窗体

1、Window基本用法

(1)Winodw窗体派生自ContentControl,有一个Content属性,里面可以放一个任意控件,因此Window下只可放一个子元素

(2)Window常用属性:Icon设置窗体的图标,ShowInTaskbar 是否在任务栏项目窗体图标,WindowState 窗口显示方式等等还有很多,可以自行设置看看。

2、去除原生边框,设置自定义背景和圆角的窗体

日常开发中:最常用的是,去掉原生的Window边框,实现自定义背景且圆角带阴影的窗体,
代码如下:

<Window x:Class="WpfApp1.MainWindow"
        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"
        xmlns:local="clr-namespace:WpfApp1" 
        Width="800" Height="400"
        Title="MainWindow" WindowStyle="None" WindowStartupLocation="CenterScreen"  
        AllowsTransparency="True" Background="Transparent"
        MouseLeftButtonDown="Window_MouseLeftButtonDown" >
    <Grid>
        <Border CornerRadius="15" Background="SeaGreen" Margin="15">
            <Border.Effect>
                <DropShadowEffect Color="#800F0E0E" ShadowDepth="5"></DropShadowEffect>
            </Border.Effect>
        </Border>
    </Grid>
</Window>

首先WindowStyle="None"去掉原生边框,设置AllowsTransparency=“True” 和Background=“Transparent” 将背景变为透明的,后续窗体具体怎么呈现可以交给里面的子元素去定义。

后台代码:

        private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.DragMove();//这个的意思是允许鼠标拖动窗体
        }

3、ResizeMode

ResizeMode的属性值及其效果如下列表所示:

属性值作用
NoResize窗口大小不可调整,最大化和最小化按钮不显示,只有关闭按钮
CanResize窗口大小可调整,最大化和最小化按钮都显示并可用
CanMinimize最小化和最大化按钮显示,但最小化按钮可用,最大化不可用
CanResizeWithGrip窗口大小可调整,最大化和最小化按钮都显示并可用

在这里插入图片描述
CanResizeWithGrip 相对于 CanResize 右多了一个“角标” 表示可调整窗体大小

3、窗体生命周期

当启动到关闭一个项目,一个窗体的生命周期(顺序如下):

窗体事件描述
1 SourceInitialized资源初始化的时候
2 Activated窗体激活的时候,窗体默认为激活状态
3 Loaded窗体加载的时候
4 ContentRendered内容呈现的时候
5 Deactivated和Activated在切换不同的窗体的时候,这个状态会不断的切换,一直触发这个两个事件
5 Closing准备关闭窗体时
6 Deactivated窗体失去焦点,失活状态
7 Closed窗体关闭时

二、Border 边框

通常与布局面板Grid 一起使用,如上面案例中即是如此,也可作为任意控件的边框也多用在控件的模板中定义控件的边框
常用属性:圆角CornerRadius,边框大小BorderThickness,边框颜色BorderBrush

<Border CornerRadius="15" Background="SeaGreen" Margin="15" BorderThickness="10" BorderBrush="Black">

三、布局控件

1、Grid

(1)Gird面板可以定义行和列,形成一个灵活的网格区域。再通过附加属性:Grid.Column=“0” 和Grid.Row=“1” 以及Grid.RowSpan=“3” 和Grid.ColumnSpan="2"等设置控件属于哪行哪列就可以进行精确的定位布局。

常用属性描述
Grid.Column=“0”表示位于哪列,从0开始
Grid.Row=“1”表示位于哪行,从0开始
Grid.RowSpan=“3”表示横跨几行
Grid.ColumnSpan=“2”表示横跨几列
ShowGridLines显示网络线,默认不显示,显示出来可以方便调试定位
ColumnDefinition和ColumnDefinitions用于定义列
RowDefinition和RowDefinitions用于定义行

(2)设置尺寸的方式

设置方式描述
绝对数值如 With=“100”
自动设置如 Width=“Auto”
按比例设置如 Height="2*”

(3)综合应用

    <Grid Background="BlueViolet">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition/><!--默认就是Auto-->
            <ColumnDefinition Width="100"/>
            <!--左右两列固定了宽度的时候,中间的如果不定义那么就是默认自动,将会自动撑满剩余控件-->
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="50"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="2*"/>
            <!--第一行固定了高度,那么剩余的设置了*和2*,那么剩余空间将会按照1比2的形式分配-->
        </Grid.RowDefinitions>
        <!--通过Grid.Column="0" Grid.Row="0"定义内部子元素的位置-->
        <Grid Grid.Column="0" Grid.Row="0" Background="Wheat"></Grid>
        <Grid Grid.Column="0" Grid.Row="1" Background="Red"></Grid>
    </Grid>

(4)共享尺寸
共享尺寸,通过在父级Grid上设置Grid.IsSharedSizeScope=“True”,然后在子元素上设置SharedSizeGroup 共享组名称,如果名称相同,则会共享尺寸。

   <Grid Grid.IsSharedSizeScope="True">
        <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="3*"/>
        </Grid.RowDefinitions>
        <Grid Background="AliceBlue"  >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="100" SharedSizeGroup="col1"/>
                <ColumnDefinition Width="3*"/>
            </Grid.ColumnDefinitions>
            <Grid Background="Bisque"></Grid>
            <GridSplitter Width="4" Background="Red"></GridSplitter>

        </Grid>
        <Grid Grid.Row="1" Background="Aquamarine" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition  SharedSizeGroup="col1" />
                <ColumnDefinition Width="3*"/>
                <ColumnDefinition Width="3*"/>
            </Grid.ColumnDefinitions>
            <Grid Background="Bisque"></Grid>
            <Grid  Grid.Row="1" Background="Red">
                <Button></Button>
            </Grid>

        </Grid>
    </Grid>

效果如下:
在这里插入图片描述

2、UniformGrid

        <UniformGrid Rows="2" Columns="5">
            <Button Height="50" Width="50" Content="Button"/>
            <Button Height="50" Width="50" Content="Button"/>
            <Button Height="50" Width="50" Content="Button"/>
            <Button Height="50" Width="50" Content="Button"/>
            <Button Height="50" Width="50" Content="Button"/>
            <Button Height="50" Width="50" Content="Button"/>
            <Button Height="50" Width="50" Content="Button"/>
        </UniformGrid>

相较于Grid,UniformGrid没有附加属性不会对子元素进行点位,会根据设置的Rows和Columns均分内部空间。如果没有设置Rows和Colums则会对内部的子元素根据子元素数量均分内部的空间,所有所谓的分行分页,具体行列取决于内部有多少子元素。

3、StackPanel

(1)派生自Panel,主要用于布局和排列,内部可以放多个控件。它可以将子元素进行水平或者竖直的排列,超过自己范围的子元素将会隐藏,不会自动切换到下一行或列,里面的子元素的位置也不可随意拖动,只能通过Margin设置子元素间的间隔
(2)常用属性

常用属性描述
Orientation=“Horizontal”该属性设置子元素的排列方式,Horizoontal表示水平堆放,Vertical竖直堆放,默认Vertical
FlowDirection=“LeftToRight”流动方向,只对Orientation=“Horizoontal” 有效,表示控件是从左到右LeftToRight,还是从右到左排列RightToLeft

(3)应用
通常用于将控件按照行或列排列布局,与其他布局控件配合使用

 <!--承接Grid中的案例,将StackPanel放在第2列,然后从0行开始,占据2行-->
        <StackPanel Background="Azure" Grid.Column="1" Grid.RowSpan="2" Orientation="Vertical" >
            <StackPanel Width="50" Background="Black" Height="50"></StackPanel>
            <StackPanel Orientation="Horizontal" FlowDirection="RightToLeft">
                <Button Height="40" Width="40" Background="Beige" Margin="10"></Button>
                <Button Height="40" Width="40" Background="Beige" Margin="10"></Button>
                <Button Height="40" Width="40" Background="Beige" Margin="10"></Button>
            </StackPanel>
        </StackPanel>

4、WrapPanel(自动换行换列)

(1) 这个控件也是按行按列排列子元素,是对WrapPanel的补充,在StackPanel的基础上,增加了自动换行换列的功能。
(2)常用属性

常用属性描述
Orientation=“Horizontal”该属性设置子元素的排列方式,Horizontal表示水平堆放,Vertical竖直堆放,默认Vertical
FlowDirection=“LeftToRight”流动方向,只对Orientation=“Horizontal” 有效,表示控件是从左到右LeftToRight,还是从右到左排列RightToLeft
ItemWidth&ItemHeight设置子元素的宽高,设置后子元素均是设置的宽高

(3)应用

<WrapPanel Background="Black" Grid.Column="0" Grid.Row="2" ItemWidth="20" ItemHeight="20" FlowDirection="RightToLeft">
            <Button Background="Beige" Margin="2"></Button>
            <Button Background="Beige" Margin="2"></Button>
            <Button Background="Beige" Margin="2"></Button>
            <Button Background="Beige" Margin="2"></Button>
            <Button Background="Beige" Margin="2"></Button>
            <Button Background="Beige" Margin="2"></Button>
</WrapPanel>

5、DockPanel

(1)定义一个区域,DockPanel中的子元素可以按相对位置水平或竖直排列,子元素不可以随意拖动
(2)常用属性

常用属性描述
LastChildFill=“True”默认最后一个元素,填空剩余控件,如果改为false将不填充
DockPanel.Dock=“Left”通过附加属性设置子元素在DockPanel的位置,Top,Right,Left,Right

(3)布局自适应页面

  <DockPanel Background="White" Grid.Column="1" Grid.Row="2" LastChildFill="True">
            <Button Height="50" Width="50" DockPanel.Dock="Bottom" Content="Bottom"></Button>
            <Button Height="50" Width="50" DockPanel.Dock="Left"  Content="Left"></Button>
            <Button Height="50" Width="50" DockPanel.Dock="Top"  Content="Top"></Button>
            <Button Height="50" Width="50" DockPanel.Dock="Right"  Content="Right"></Button>
            <!--最后一个不设置大小的情况下:默认填空剩余控件-->
            <Button></Button>
        </DockPanel>

6、Canvas

常用属性描述
Canvas.Left通过使用附加属性,如Canvas.Left 和Canvas.Top来定位子元素在Canvas内部的位置。如果Canvas大小发生了变化,内部的子元素位置也会发生变化,但是子元素相对于Canvas的位置是不变的。
ClipToBounds=“False”Canvas是默认允许子元素超出自己边界的,不会裁剪;设置ClipToBounds="True"则会裁剪

1 每个元素必须使用附加属性指定位置,否则都会出现在左上角。
2 Canvas 不能在指定位置时超过2个坐标,如:Canvas.Left=“10” Canvas.Top=“10” Canvas.Right=“10”
那么最后一个将会失效。

        <Canvas Height="100" Width="100" Background="Red" ClipToBounds="False">
            <Button Height="20" Width="200" Canvas.Left="10" Canvas.Top="10"></Button>
        </Canvas>

如下图所示:
在这里插入图片描述

7、ViewBox

定义一个内容修饰器,以便拉伸或缩放单一子项使其填满可用的控件

常用属性Strech

Strech属性枚举值描述
None不做缩放,放入子元素控件的大小保持不变
Fill拉伸子元素控件以填满整个ViewBox内部的控件,有可能会导致变形
Uniform内部子元素如果设置了宽高,那么ViewBox会将子元素按照宽高比例去缩放。如果子元素宽为200,高100,那么无论窗口如何调整大小,该子元素控件会永远保持2:1的比例在ViewBox内去填充,但不一定填满整个控件。
UniformToFill内部子元素同样会保持自己的纵横比并且一定会填满整个控件,但是超过ViewBox的部分将会被裁剪
    <Viewbox Stretch="Uniform">
        <!--ViewBox内只可放一个子元素,设置的Stretch=Uniform 则表示不管窗体大小如何变化,
        子元素都将保持这个比例等比缩放-->
        <Grid Width="1920" Height="1080" Background="Aqua">
            <!--里面还可以放置其他的控件-->
        </Grid>
    </Viewbox>

7、Panel.ZIndex附加属性在布局中的使用

      <StackPanel Orientation="Horizontal">
            <Grid Height="100" Width="100" VerticalAlignment="Top">
                <Button Width="80" Height="80"></Button>
                <Button Width="40" Height="40" Background="Red"></Button>
            </Grid>

            <Grid Height="100" Width="100" VerticalAlignment="Top">
                <Button Width="80" Height="80" Panel.ZIndex="1"></Button>
                <Button Width="40" Height="40" Background="Red"></Button>
            </Grid>
        </StackPanel>

在这里插入图片描述
默认同一个位置,控件的叠放是后面的控件就放置在上层,如果设置Panel.ZIndex则可以按照自定义的叠放顺序放置。

四、按钮与输入框

1、Button

常用属性描述
Content=“按钮”直接设置或者使用在<Button>标签内放一个子控件
Click点击事件,一般点击按钮后做什么业务逻辑都在这里
Command在开发项目时会使用到,可以绑定命令,效果同Click
IsDefault当用户按下Enter的时候,相当于点击该按钮,就会调用该按钮的点击事件,多用于登录界面
IsCancel当用户按下Esc的时候相当于点击了该按钮,同样登录界面用的较多
      <Button Height="40" Width="100" Background="Beige" Margin="10" Click="Button_Click" 
                        IsCancel="True" IsDefault="True" Command="{Binding xxCommand}">
             <TextBlock Text="按钮Content"></TextBlock>
     </Button>

2、ReapButton

作用是当用户鼠标左键按住该按钮时,会一直触发点击事件,主要应用于一些播放器的快进等功能

<RepeatButton  Delay="20" Interval="1000" Click="repButton_Click"></RepeatButton>
常用属性描述
Delay表示从用户按下鼠标左键到开始重复发送Click事件的延迟时间(毫秒),Delay的数值必须>=0。
Interval表示当用户按下鼠标左键时,每次发送Click事件的时间间隔(毫秒),Interval的数值必须>=0。

3、TextBox

<TextBox Width="100" Height="40" TextWrapping="Wrap" 
   TextAlignment="Center" Text="1234546546484684684646456464646">
常用属性描述
Text文本内容
TextWrapping文本是否自动换行,默认一行显示
TextAlignment文本对齐方式

4、PasswordBox

<PasswordBox Password="1213113" PasswordChar="*" Width="80" Height="30"
    VerticalContentAlignment="Center" HorizontalContentAlignment="Right"></PasswordBox>
常用属性描述
Password密码文本信息
PasswordChar密码字符,默认是圆点
VerticalContentAlignment & HorizontalContentAlignment设置内部密码文本的对齐方式

5、RichTextBox

(1)对System.Windows.Documents.FlowDocument对象进行丰富操作的编辑控件,与TextBox一样派生自TextBoxBase

常用属性描述
Document获取或设置RichTextBox的SystemWindows.Documents.FlowDocument表示的内容
IsDocumentEnabled用户是否可以交互(RichTextBox中的UIElement和 ContentElement中的对象),false用户将无法操作文档内容进行交互
Selection当前选定内容

(2)FlowDocument 可以设置一些文档通用的属性,属性如下:

【ColumnGap列间隔】、 【PageWidth页宽】、 【lsColumnWidthFlexible列宽是灵活还是固定】
【ColumnRuleBrush绘制列之间标尺的颜色】、 【PagePadding页内边距】 、【PageHeight页高度】、 【ColumnWidth列宽】、【Blocks内容的顶级块元素】、 【FlowDirection流中的内容的相对方向】、 【ContentStart内容的开始位置】 、【ContentEnd内容的结束位置】、【LineHeight各行内容的高度】还有各种文字属性FontFamily,FontSize,FontWeight等等

(3)FlowDocument中的元素:

常用属性描述
Block为所有块级别流内容元素提供基类的抽象类
Paragraph用于将内容分组到一个段落中的块级别流内容元素
Run旨在包含一连串格式化或非格式化文本的内联级别流内容元素。Inline
Section用于对其他 System.Windows.Documents.Block元素进行分组的块级别流内容元素
Hyperlink提供用于在流内容中承载超链接的功能的内联级别的流内容元素
InlineUIContainer内联级别的流内容元素,可以将UI元素嵌入到流内容中
BlockUlContainer块级别流内容元素可以将UI元素嵌入到流内容中

(4)案例

        <Grid Width="1920" Height="1080" Background="Aqua">
            <!--默认IsDocumentEnabled是不可交互的-->
            <RichTextBox IsDocumentEnabled="True" >
                <!--【1】我是FlowDocument是一个文档,RichTextBox用我来承接内容-->
                <!--我可以设置文档的对齐方式,以及基本的字体大小,颜色,列间隔,页宽,行高等等文档的属性-->
                <FlowDocument PagePadding="20" TextAlignment="Center" PageWidth="1500">
                    <!--【2】Paragraph是文档中的一个段落-->
                    <Paragraph TextIndent="20" LineHeight="80" Background="Red" >
                        <!--可以设置行高LinHeight 与 缩进TextIndent-->
                        <Run Text="行内元素Run是放在Paragraph中的,一般表示一句话。" FontSize="40"></Run>
                        <Run Text="我也是行内元素Run,我接着上一个Run,我们之间不换行" FontSize="40" Foreground="Aqua"></Run>
                    </Paragraph>
                    <!--段落与段落之间是要换行的-->
                    <Paragraph TextIndent="20" LineHeight="100" TextAlignment="Center"  Foreground="Blue" Background="BlanchedAlmond">
                        <Run Text="我是第二个Paragraph中的内容,与上一个段落是要换行的" FontSize="60"></Run>
                        <!--我是行内元素,超链接-->
                        <Hyperlink  Click="Hyperlink_Click" FontSize="40">
                            <Run Text="网址"  ></Run>
                            <Run Text="dawd"></Run>
                            <TextBlock Text="我是UI元素也可以放在这里" ></TextBlock>
                        </Hyperlink>
                    </Paragraph>
                    <Paragraph TextIndent="20" Foreground="Blue" Background="BlanchedAlmond" FontSize="30">
                        <!-- 一般文档中的行内元素放在InlineUIContainer中,InlineUIContainer只能放一个子元素-->
                        <Run Text="我是Run元素哦,后面是InlineUIContainer"></Run>
                        <InlineUIContainer>
                            <TextBlock Text="我是放在InlineUIContainer里的TextBlock"></TextBlock>
                        </InlineUIContainer>
                        <!--由此可见Run 和 InlineUIContainer中的内容是不换行的-->
                    </Paragraph>
                    <!--我是BlockUIContainer,是换行的-->
                    <BlockUIContainer >
                        <TextBlock Text="我是放在BlockUIContainer里的TextBlock" FontSize="40"></TextBlock>
                    </BlockUIContainer>
                    <BlockUIContainer >
                        <TextBlock Text="我是放在BlockUIContainer里的TextBlock" FontSize="40"></TextBlock>
                    </BlockUIContainer>
                </FlowDocument>
            </RichTextBox>
        </Grid>
        private void Hyperlink_Click(object sender, RoutedEventArgs e)
        {
            Process process = new Process();
            process.StartInfo.FileName = "www.baidu.com";
            process.Start();
        }

在这里插入图片描述
以上介绍了RichTextBox的基本属性和用法,对于RichTextBox一般还有有一些文本编辑功能,如复制粘贴,设置对齐方式,插入文本,保存文件等等内容还是比较多的,后续有机会在进行专题讲解

五、文本控件

1、TextBlock

(1)这是一个轻量级的文本控件,多用于一些简短的标题或文字,或者成为内容控件的子元素作为文本呈现用。

(2)一般用法如下:

      <StackPanel>
                <!--【1】单独使用-->
                <TextBlock Text="###大标题" TextWrapping="Wrap" FontSize="30"></TextBlock>
                <!--【2】内部组合使用,多用于一些界面上标题后面还接着一行小英文标题-->
                <TextBlock>
                    <TextBlock Text="一级大标题" FontSize="30"></TextBlock>
                    <TextBlock Text="二级标题" FontSize="20"></TextBlock>
                    <Run Text="最后解释语" FontSize="10"></Run>
                </TextBlock>
                <!--【3】作为其他元素的子元素使用-->
                <Button Height="20" Width="220">
                    <Button.Content>
                        <TextBlock Text="我是作为按钮的Content呈现的"></TextBlock>
                    </Button.Content>
                </Button>
            </StackPanel>

在这里插入图片描述

2、Label

(1)一个可以具有Content属性的文本控件,一般用作文本显示。
由于该控件具有Content属性,因此可以在Content 中组合多个子元素控件来显示内容,这样显示的内容就更加丰富了。

  <Label Content="我是Label" BorderThickness="1" BorderBrush="Black"></Label>
  <Label>
        <Label.Content>
               <StackPanel Orientation="Horizontal">
                    <TextBlock Text="1213dww" VerticalAlignment="Center"></TextBlock>
                    <Button Height="40" Width="40"></Button>
               </StackPanel>
        </Label.Content>
  </Label>

六、单选和多选框

1、RadioButton单选框

一般多用于选择性别,开关状态等设置

常用属性描述
Content按钮的内容
GroupName组名,这个在使用中需要注意,如果多个RadioButton设置了同一个组名,那么它们之间是互斥的,只有一个能被选中,不同组的不互斥
IsChecked是否选中的状态
<RadioButton IsChecked="True" Content="" GroupName="sex"></RadioButton>
<RadioButton  Content="" GroupName="sex"></RadioButton>

2、CheckBox多选框

多选框一般多用于爱好选项,权限选择等一些需要选择多项内容的场景

常用属性描述
Content按钮的内容
IsThreeState确定控件是否支持两个或三个状态,默认为false,支持三个状态
IsChecked是否选中的状态
 <StackPanel Orientation="Horizontal">
     <CheckBox Content="羽毛球" Margin="10" IsChecked="True"></CheckBox>
     <CheckBox Content="足球" Margin="10" IsThreeState="True"></CheckBox>
     <CheckBox Content="篮球" Margin="10"></CheckBox>
     <CheckBox Content="乒乓球" Margin="10"></CheckBox>
 </StackPanel>

单选框和多选框都具有 Checked 已选中时事件,UnChecked 未选中的事件,Click点击的事件用于处理其选择时的逻辑

七、Image

1、基本使用

用于展示图片,主要属性就是Source图片资源路径

<Image Height="100" Width="50" Source="Images/1.jpg" Stretch="Uniform"> </Image>

2、修改数据文件的生成操作

什么是数据文件呢?
数据文件,其实指的就是应用程序依赖的非可执行文件,例如xaml、图像、视频等。如1.jpg。
wpf支持对数据文件进行配置、识别及使用。在wpf中对数据文件分为三类:

  1. 资源文件—被编译进可执行文件exe或者类库dll的数据文件
  2. 内容文件—与程序集有显式关联关系的独立的数据文件
  3. 源站点文件—与程序集没有关联的独立数据文件

如下图所示:如果我们将生成操作设置Resource,那么该文件就是资源文件。会被编译进exe或dll中。
如果生成操作设置为内容,那么重新生成之后,该文件就是内容文件。内容文件会在编译后输出到Debug/Release目录下。如果内容文件是项目的背景图片,则可以直接在Debug目录下通过更换图片实现更换背景。
在这里插入图片描述
【生成操作=内容】 通常配合【复制到输出目录=始终复制】一起使用。

3、研究Image中的Source的赋值

查看官方文档中:ImageSource的派生关系
方式一:通过BitmapSource的Create方法

// Define parameters used to create the BitmapSource.
PixelFormat pf = PixelFormats.Bgr32;
int width = 200;
int height = 200;
int rawStride = (width * pf.BitsPerPixel + 7) / 8;
byte[] rawImage = new byte[rawStride * height];

// Initialize the image with data.
Random value = new Random();
value.NextBytes(rawImage);

// Create a BitmapSource.
BitmapSource bitmap = BitmapSource.Create(width, height,
    96, 96, pf, null,
    rawImage, rawStride);

// Create an image element;
Image myImage = new Image();
myImage.Width = 200;
// Set image source.
myImage.Source = bitmap;

方式二:通过BitmapSource的派生类BitmapImage(大多是这种方式)

 this.img.Source = new BitmapImage(new Uri("Images/1.jpg", UriKind.Relative));

后续开发中会存在多种给Source赋值的情况,不过各种图片数据大多最终转为为BitmapImage然后赋值给Source

4、相对路径&绝对路径&Pack Uri的使用

1 相对路径的使用(无论是将图片设为资源 还是内容,访问都是没有问题的):

 this.img.Source = new BitmapImage(new Uri("Images/1.jpg", UriKind.Relative));

2 绝对路径的使用:

  • 使用AppDomain,直接到Debug/Release下找文件
    这种绝对路径引用的文件是可以完全独立于项目之外的,操作上只需代码中指定路径后,在Debug/Release目录下,建立该文件的路径,程序即可找到。这种是独立于程序之外,因此不在乎该文件是编译成资源,还是内容。
//Debug目录下新建一个Imgs,然后将1.jpg放进去,只要指定过路径,就可以引用进项目使用
this.img.Source=new BitmapImage(new Uri(AppDomain.CurrentDomain.BaseDirectory+ "Imgs/1.jpg", UriKind.Absolute));
  • Pack Uri方式设置绝对路径

如果我们使用的文件的生成操作为Resource, 则此文件为资源文件,
可使用pack://application的方式,引用此资源文件:

this.img.Source=new BitmapImage(new Uri("pack://application:,,,/Images/1.jpg", UriKind.Absolute));

如果我们使用的文件的生成操作为内容, 则此文件为内容文件,
可使用pack://application的方式,引用此内容文件:

this.img.Source=new BitmapImage(new Uri("pack://application:,,,/Images/1.jpg", UriKind.Absolute));

从上面看起来,好像都一样,那么内容文件和资源在使用pack://application:,方式引用上有什么区别呢?
区别在于:如pack://application:,/Images/1.jpg改为pack://application:,/Images/2.jpg,并且2.jpg不在项目的Images的目录下,那么即使项目生成后在Debug/Release目录下加一个Images,Images里放个2.jpg,一样无法引用2.jpg。因为内容文本独立但是和与程序集有显式关联关系,显示关联的特征就是包含在项目结构目录下

源站点文件指的是与程序集没有必然关联关系的独立数据文件,需要
使用pack://siteoforigin去引用资源:

//表示要在程序集dll或者exe之外去找文件
//如果在该文件属性的生成操作设置资源的情况下,这个路径下将无法找到1.jpg
//这种效果同AppDomain.CurrentDomain.BaseDirectory类似
this.img.Source = new BitmapImage(new Uri("pack://siteoforigin:,,,/Images/1.jpg", UriKind.Absolute));

八、其他

1、Slider

Slider滑块通常用于调整数值范围的阀门控件

常用属性描述
Value当前刻度值
Minimum最小刻度
Maximum最大刻度
Orientation滑块的方向,Horizontal为水平方向
TickPlacement刻度的位置,Both表示上下都有刻度
IsSnapToTickEnabled将滑块移动到最近的刻度线,默认为False,不会将滑块每次的移动都调整到客户线处
IsDirectionReversed将刻度调转方向,默认False刻度从左到有;设置为Ture后,将会调整为从右到左
IsSelectionRangeEnabled默认False,不可以选择刻度范围,设置为Ture后,SelectionStart和SelectionEnd的属性值才能生效
SelectionStart,SelectionEnd刻度范围的开始结束值,一般可用于某个数字的正常范围设定
<Slider Width="300" VerticalAlignment="Top" TickFrequency="10" TickPlacement="Both" 
Minimum="0" Maximum="100"  Orientation="Horizontal" LargeChange="20" 
IsSnapToTickEnabled="True" IsDirectionReversed="True" 
IsSelectionRangeEnabled="True" SelectionStart="10" SelectionEnd="30"></Slider>

2、其他

DatePicker
Carlender
ProgressBar
ToolBar
ToolBarTray
StatusBar
TreeView
ScrollViewer
WindowFormsHost
MediaElement
Rectangle
Eillpse
Polygon
Path
GroupBox,
Expander.
Frame,
TabControl,
ComboBox,
ListBox,
ListView,
DataGrid,
Menu,
ContextMenu,
以上控件详细介绍会逐步更新

如想详细了解以上控件或者更多的控件可以查看:
官方文档:System.Windows 命名空间
官方文档:System.Windows.Controls 命名空间

九、Dispatcher

在我们了解了控件的基本使用和属性之后,在使用控件的过程就不可避免的会遇到一个跨线程操作UI的问题。而Dispatcher就可以解决这个问题。

1、Dispatcher的作用

(1)在WPF中Dispatcher的作用 是为管理的线程的工作项队列提供服务
WPF中的主线程负责:接收输入,处理事件,绘制UI等工作。正因UI界面是由主线程创建并维护,因此子线程不能是直接更改由主线程负责处理的UI界面,如果强行更改就会报错。为了解决这一问题Dispatcher中提供了Invoke 和BeginInvoke两个方法。
(2)具体原理:
先看Invoke 和BeginInvoke的方法,方法原型如下:

public void Invoke(Action callback);
public DispatcherOperation BeginInvoke(Delegate method, params object[] args);

在结合看一下WinForm中对这两个方法的解释会更容易理解,WinForm的解释如下。

Control.Invoke (Delegate method) :在拥有此控件的基础窗口句柄的线程上执行指定的委托。
Control.BeginInvoke(Delegate method) :在创建控件的基础句柄所在线程上异步执行指定委托。

其实WPF中控件使用Control.Dispatcher.Invoke()和WinForm中差不多的意思,只不过WPF又封装了一层上去。
结合以上内容我们知道,其实本质上就是在子程序中,通过Invoke 和BeginInvoke将需要做的UI操作以委托的形式交给了UI主线程去操作,那么这样就解决了跨线程操作的问题。

2、跨线程案例说明:

如果子线程直接操作主线程UI,将会报错。如下图所示:
在这里插入图片描述
通过Dispatcher调用则不会报错。

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            Task task = new Task(() =>
            {
                while (true)
                {
                    this.tbk_Date.Dispatcher.Invoke(() =>
                    {
                        this.tbk_Date.Text = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    });
                    Thread.Sleep(800);
                }
            });
            task.Start();
        }

3、Invoke和BeginInvoke的区别

Invoke是在UI线程同步执行操作
BeginInvoke是在UI线程上异步执行操作
案例如下:
在这里插入图片描述
由上面案例可知:使用Invoke是在UI线程上同步执行的,上一个操作做完,才可以做下一个。
但是BeginInvoke就是异步执行的,并不是按调用顺序一个个执行,而是无序的异步执行。


总结

总目录
以上就是今天要讲的内容,本文介绍了日常开发过程中经常会使用到的控件,了解这些控件和属性对于我们日后的开发是必不可少的储备知识。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐