WPF桌面端开发1-常用组件

基本组件

展示类

  • Button
  • RadioButton
  • CheckBox
  • Image
  • Label
  • TextBlock
  • ProgressBar
  • ComboBox
  • Rectangle

输入类

  • TextBox
  • PasswordBox
  • RichTextBox

TextBlock

选中和悬浮变色

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<TextBlock
Padding="13"
FontSize="14"
Text="{Binding directorname}"
TextTrimming="CharacterEllipsis">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="{Binding state, Converter={StaticResource ColorTextConvert}}" />
<Setter Property="FontWeight" Value="{Binding state, Converter={StaticResource TextBoldConverter}}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="#2D8CF0" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>

文字阴影

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<TextBlock
Grid.Row="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="14"
Foreground="White"
Text="退出控制">
<TextBlock.Effect>
<DropShadowEffect
Direction="290"
Opacity="0.7"
ShadowDepth="2"
Color="Black" />
</TextBlock.Effect>
</TextBlock>

文本换行

方式1

转义字符换行

代码中

1
this.TextBlock1.Text = "AAAAAAA\nBBBBBBBB";

XAML中

1
<TextBlock Text="AAAAAAA&#x000A;BBBBBB" />

方式2

设置自动换行

1
<TextBlock Width="60" TextWrapping="Wrap" Text="AAAAAAA BBBBBB"/>

方式3

使用InLines属性的LineBreak来换行

简单的来说就是,显示的XAML表示用

1
2
3
4
5
<TextBlock Width="60" TextWrapping="Wrap"> 
<Run>AAAAAA</Run>
<LineBreak/>
<Run>BBBBBB</Run>
</TextBlock>

后台代码添加

1
2
3
TextBlock1.Inlines.Add(New Run("AAAAAA"));
TextBlock1.Inlines.Add(New LineBreak());
TextBlock1.Inlines.Add(New Run("BBBB"));

另外如果RUN里面有大量的文字表示,超过了TextBlock的Width时候,文字会被剪切掉,而不是自动换行,这点需要注意一下

Button

1
2
3
4
5
6
7
8
<Button
Width="500"
Height="500"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Panel.ZIndex="3"
Click="Button_Click"
Content="" />

要想没有内容的按钮可点击要设置

1
2
3
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
Content=""

分割线

1
2
3
4
<Rectangle
Grid.Column="1"
Width="1"
Fill="#eeeeee" />

TextBox

文字居中

1
2
3
4
5
6
7
8
9
<TextBox
x:Name="txbKey"
Padding="10,0,0,0"
VerticalContentAlignment="Center"
FontSize="18"
Foreground="gray"
Text=""
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />

单行不换行

1
2
3
4
5
6
7
8
9
10
11
12
13
<TextBox
Grid.Column="1"
Margin="6,0,6,0"
VerticalContentAlignment="Center"
Background="#eeeeee"
BorderBrush="{x:Null}"
BorderThickness="0"
FontSize="14"
Foreground="#333333"
MaxLines="1"
Text=""
TextAlignment="Left"
TextWrapping="NoWrap" />

文字换行与滚动条

1
2
3
4
5
6
7
8
<TextBox
Name="CommTb"
Height="100"
Margin="0,10,0,0"
VerticalAlignment="Top"
BorderBrush="#f0f0f0"
TextWrapping="Wrap"
VerticalScrollBarVisibility="Auto" />

ComboBox

1
2
3
4
5
6
7
8
9
10
11
12
<ComboBox
x:Name="ip_cb"
Height="auto"
Margin="0,0,0,0"
Padding="10,0,0,0"
VerticalContentAlignment="Center"
Cursor="Hand"
DisplayMemberPath="Value"
FontSize="14"
SelectedValuePath="Key"
SelectionChanged="ip_cb_SelectionChanged"
Style="{StaticResource ComboBoxStyle}" />

数据绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var addressList = ZConfig.ipaddressList();
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Key", typeof(string)));
dt.Columns.Add(new DataColumn("Value", typeof(string)));

for (int i = 0; i < addressList.Count; i++)
{
dt.Rows.Add(addressList[i], addressList[i]);
}

ip_cb.ItemsSource = dt.DefaultView;
if (addressList.Count > 0)
{
ip_cb.SelectedIndex = 0;
}

注意

ip_cb.SelectedIndex = 0;会触发回调。

选中回调

1
2
3
4
5
6
7
private void ip_cb_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
if (ip_cb.SelectedValue != null)
{
var localIP = ip_cb.SelectedValue.ToString();
}
}

获取到的是SelectedValuePath对应的值

1
2
3
4
//保存的ID
ZCommonData.classid = Convert.ToInt32(cmbClass.SelectedValue.ToString());
//显示的名称
ZCommonData.classname = cmbClass.Text;

Image

Image的Stretch属性

  • Uniform(默认) —— 这代表图片会均匀的变大和缩小,保证了图片的比例不失调,而往往我们设置的宽和高并不符合图片的比例,因此显示效果就不是我们预期所想。

  • None——图片会按原始大小显示。

  • Fill——图片会按照设置的Width和Height显示,比例会失调。

  • UniformToFill——图片会按照设置的Width和Height显示,但图片是均匀变大和缩小的,比例不失调,超出显示范围的图像会被截掉。

小图片不缩放,大图片缩放

1
2
3
4
5
6
<Viewbox>
<Image Width="{Binding RelativeSource={RelativeSource Self}, Path=Source.PixelWidth}"
Height="{Binding RelativeSource={RelativeSource Self}, Path=Source.PixelHeight}"
Source="{Binding CtrlImage, IsAsync=True}"
Stretch="None" />
</Viewbox>

CheckBox

1
2
3
4
5
<CheckBox
Content="苹果"
IsChecked="True"
IsEnabled="False"
Style="{StaticResource ZCheckBoxStyle}" />

自定义样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<Style x:Key="ZCheckBoxStyle" TargetType="{x:Type CheckBox}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="OverridesDefaultStyle" Value="False" />
<Setter Property="FocusVisualStyle" Value="{DynamicResource CheckBoxFocusVisual}" />
<Setter Property="Height" Value="20" />
<Setter Property="IsChecked" Value="False" />

<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Rectangle
x:Name="CheckBoxRectangle"
Fill="White"
Opacity="0.3"
RadiusX="2"
RadiusY="2" />
<Rectangle
x:Name="CheckBoxRectangleOut"
Width="18"
Height="18"
RadiusX="2"
RadiusY="2"
Stroke="#DCDDDE"
StrokeThickness="1" />
<!-- 选中的对勾 -->
<Border
x:Name="CheckedMark"
Width="18"
Height="18"
Background="#2D8CF0"
CornerRadius="2"
Visibility="Collapsed">
<Grid Width="18" Height="18">
<Path
Data="M3,9 L9,14"
SnapsToDevicePixels="False"
Stroke="White"
StrokeThickness="2" />
<Path
Data="M8,14 L15,4"
SnapsToDevicePixels="False"
Stroke="White"
StrokeThickness="2" />
</Grid>
</Border>
</Grid>
<TextBlock
Grid.Column="1"
Margin="4,0,0,0"
VerticalAlignment="Center"
FontSize="14"
Foreground="#333"
Text="{TemplateBinding Content}" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="CheckedMark" Property="Visibility" Value="Visible" />
<Setter TargetName="CheckBoxRectangle" Property="Fill" Value="White" />
<Setter TargetName="CheckBoxRectangle" Property="Opacity" Value="1" />
<Setter TargetName="CheckBoxRectangleOut" Property="Stroke" Value="#2D8CF0" />
</Trigger>

<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="CheckedMark" Property="Background" Value="#ddd" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

定位常用属性

在设计UI时,WPF为我们提供了一些属性用于精确定位元素

其中最常用的有三个:Alignment(包括水平,垂直),Margin,Padding,

具体用法如下:

  • HorizontalAlignment: 子元素在水平方向的对齐方式,有左对齐,右对齐,中间对齐,拉伸填充等四种方式。

  • VerticalAlignment:子元素在垂直方向的对齐方式,有顶端对齐,底部对齐,中间对齐,拉伸填充等四种方式。

  • Margin:用于指定元素与其父级或同级之间的距离,包括上下左右四个值。也可通过使用 Margin=”20”同时指定四个值。

  • Padding:用于指定元素与其子级之间的距离,包括上下左右四个值。也可通过使用Padding=”20”同时指定四个值。

内容定位

1
2
VerticalContentAlignment="Center"
HorizontalContentAlignment="Center"

Padding

组件和容器有的支持Padding有的不支持,这里统计一下

容器

支持Padding的

1
2
3
4
5
6
<Border Padding="10" />
<ScrollViewer Padding="10" />
<ItemsControl Padding="10" />
<ListBox Padding="10" />
<ListView Padding="10" />
<DataGrid Padding="10" />

不支持Padding的

1
2
3
4
5
6
7
<Canvas />
<StackPanel />
<WrapPanel />
<DockPanel />
<Grid />
<UniformGrid />
<Viewbox />

可以看出静态容器都不支持Padding。

组件

支持Padding的

1
2
3
4
5
6
7
8
9
<Button Padding="10" />
<RadioButton Padding="10" />
<Label Padding="10" />
<TextBlock Padding="10" />
<ProgressBar Padding="10" />
<ComboBox Padding="10" />
<TextBox Padding="10" />
<RichTextBox Padding="10" />
<PasswordBox Padding="10" />

不支持Padding的

1
2
<Rectangle />
<Image />

可以看出组件大都支持Padding。

WPF 中的Width 与 ActualWidth

在WPF中,控件有Width 和 ActualWidth两个属性,二者的区别如下:

Width:是我们期望控件应有的宽度,是可读写的,可在xaml文件中设置,也可在程序中设置。如果没有设置,Width的值为NaN(Not a Number)

ActualWidth:是控件Render的实际宽度,控件Render之前,它的值为0,。该属性是只读的。

ScrollViewer无法滚动

需要给ScrollViewer注册一个鼠标滚轮事件!

1
2
3
4
5
6
<ScrollViewer
HorizontalScrollBarVisibility="Disabled"
PreviewMouseWheel="ScrollViewer_PreviewMouseWheel"
VerticalScrollBarVisibility="Visible">

</ScrollViewer>

后台代码实现:

1
2
3
4
5
6
7
8
9
10
private void ScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
if (sender is ScrollViewer) {
ScrollViewer sv = (ScrollViewer)sender;
MouseWheelEventArgs eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta);
eventArg.RoutedEvent = UIElement.MouseWheelEvent;
eventArg.Source = sender;
sv.RaiseEvent(eventArg);
}
}

居然ScrollViewer控件默认不带滚动!!!

去掉组件获取焦点的虚框

1
2
3
4
5
6
7
8
9
10
11
12
13
<CheckBox
Content="鼠标左键确认"
FocusVisualStyle="{x:Null}" />

<Button
Height="26"
Background="#6D9A15"
BorderThickness="0"
Content="[取色/确认] (Alt)"
Cursor="Hand"
FocusVisualStyle="{x:Null}"
FontFamily="Microsoft YaHei Light"
/>

也就是设置属性

1
FocusVisualStyle="{x:Null}"

或者

1
2
3
<Style x:Key="MyButton" TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>

自定义字体

一、准备字体文件,以TTF格式结尾;复制到项目中,并设置Build Action(生成操作)Resource(资源)

二、在App.xaml中或者你需要的地方添加字体资源的定义;

资源定义处引用的并不是字体文件的名称,而是字体名称,字体的具体名称可以打开字体文件进行查看。

image-20230218164256108

引用字体的时候不用写文件的名称

字体名称一定要写

1
2
3
<Application.Resources>
<FontFamily x:Key="UnidreamLed">pack://application:,,,/Font/#UniDreamLED</FontFamily>
</Application.Resources>

当然写上文件名称也可以

1
2
3
<Application.Resources>
<FontFamily x:Key="UnidreamLed">Pack://application:,,,/Font/UnidreamLED.ttf#UniDreamLED</FontFamily>
</Application.Resources>

或者页面内引用

1
2
3
<Window.Resources>
<FontFamily x:Key="UnidreamLed">pack://application:,,,/Font/#UniDreamLED</FontFamily>
</Window.Resources>

使用

1
<TextBlock Text="10:30" FontFamily="{StaticResource UnidreamLed}" FontSize="16"/>

边框阴影

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<Border
Grid.Row="1"
Margin="4"
Background="White"
CornerRadius="4">
<Border.Effect>
<DropShadowEffect
BlurRadius="8"
Direction="270"
Opacity="0.2"
RenderingBias="Quality"
ShadowDepth="2"
Color="Black" />
</Border.Effect>
</Border>

注意

设置阴影的Border一定要设置Margin,否则不显示。