WPF笔记杂项控件与样式
接上一篇《WPF笔记汇总之消息框与界面控件》,这篇汇总一些比较常用的杂项控件,如日历,边框,滑块,进度条,组合框,日期拾取器,扩展控件等,顺便总结样式及触发器的一些常用的用法。
文章目录
1. 杂项控件
1.1 Border
Border设置的边界并不会显示出来,除非你为它定义一个 背景(Background)或者 边界刷(BorderBrush)和 边界宽度(BorderThickness),还可以添加一个 CornerRadius 圆角属性。它可以只定义一个特定值,并应用于全部四个角。按照右上、左上和右下、左下分辨定义不同的值。边界宽度(BorderThickness )属性是 Thickness,背景属性的类型是画刷(Brush)
<StackPanel Margin="10">
<!--普通边框-->
<Border Background="GhostWhite"
BorderBrush="Silver"
BorderThickness="1"
CornerRadius="8,8,3,3">
<StackPanel Margin="10">
<Button>Button 1</Button>
<Button Margin="0,10">Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Border>
<TextBlock></TextBlock>
<!--设置边框-->
<Border Background="GhostWhite" BorderBrush="DodgerBlue" BorderThickness="1,3,1,5">
<StackPanel Margin="10">
<Button>Button 1</Button>
<Button Margin="0,10">Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Border>
<TextBlock></TextBlock>
<!--渐变背景色-->
<Border BorderBrush="Navy" BorderThickness="1,3,1,5">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="LightCyan" Offset="0.0" />
<GradientStop Color="LightBlue" Offset="0.5" />
<GradientStop Color="DarkTurquoise" Offset="1.0" />
</LinearGradientBrush>
</Border.Background>
<StackPanel Margin="10">
<Button>Button 1</Button>
<Button Margin="0,10">Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Border>
</StackPanel>
1.2 Slider
通过沿水平或垂直线拖动滑块(Thumb)来选择数值的控件。
<StackPanel Margin="10" VerticalAlignment="Center">
<DockPanel VerticalAlignment="Center" Margin="10">
<TextBox Text="{Binding ElementName=slValue, Path=Value, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" TextAlignment="Right" Width="40" />
<Slider Maximum="255" TickPlacement="BottomRight" TickFrequency="5" IsSnapToTickEnabled="True" Name="slValue" />
</DockPanel>
<TextBlock></TextBlock>
<DockPanel VerticalAlignment="Center" Margin="10">
<Label DockPanel.Dock="Left" FontWeight="Bold">R:</Label>
<TextBox Text="{Binding ElementName=slColorR, Path=Value, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" TextAlignment="Right" Width="40" />
<Slider Maximum="255" TickPlacement="BottomRight" TickFrequency="5" IsSnapToTickEnabled="True" Name="slColorR" ValueChanged="ColorSlider_ValueChanged" />
</DockPanel>
<DockPanel VerticalAlignment="Center" Margin="10">
<Label DockPanel.Dock="Left" FontWeight="Bold">G:</Label>
<TextBox Text="{Binding ElementName=slColorG, Path=Value, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" TextAlignment="Right" Width="40" />
<Slider Maximum="255" TickPlacement="BottomRight" TickFrequency="5" IsSnapToTickEnabled="True" Name="slColorG" ValueChanged="ColorSlider_ValueChanged" />
</DockPanel>
<DockPanel VerticalAlignment="Center" Margin="10">
<Label DockPanel.Dock="Left" FontWeight="Bold">B:</Label>
<TextBox Text="{Binding ElementName=slColorB, Path=Value, UpdateSourceTrigger=PropertyChanged}" DockPanel.Dock="Right" TextAlignment="Right" Width="40" />
<Slider Maximum="255" TickPlacement="BottomRight" TickFrequency="5" IsSnapToTickEnabled="True" Name="slColorB" ValueChanged="ColorSlider_ValueChanged" />
</DockPanel>
</StackPanel>
private void ColorSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
Color color = Color.FromRgb((byte)slColorR.Value, (byte)slColorG.Value, (byte)slColorB.Value);
this.Background = new SolidColorBrush(color);
}
1.3 ProgressBar
进度条控件,显示进度用的。
<Window x:Class="WpfStudy.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:WpfStudy"
mc:Ignorable="d"
Title="MainWindow" Height="200" Width="300"
Name="wnd"
Icon="me.png" WindowStartupLocation="CenterScreen"
ContentRendered="Window_ContentRendered">
<StackPanel>
<!--带文本显示进度条演示-->
<Grid Margin="20" Height="30">
<ProgressBar Minimum="0" Maximum="100" Name="pbStatus" />
<TextBlock Text="{Binding ElementName=pbStatus, Path=Value, StringFormat={}{0:0}%}" HorizontalAlignment="Center" VerticalAlignment="Center" />
</Grid>
<!--不确定进度条-->
<Grid Margin="20" Height="30">
<ProgressBar Minimum="0" Maximum="100" IsIndeterminate="True" />
</Grid>
</StackPanel>
private void Window_ContentRendered(object sender, EventArgs e)
{
BackgroundWorker worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += worker_DoWork;
worker.ProgressChanged += worker_ProgressChanged;
worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 100; i++)
{
(sender as BackgroundWorker).ReportProgress(i);
Thread.Sleep(100);
}
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pbStatus.Value = e.ProgressPercentage;
}
1.4 GroupBox
组合框控件,把相关一类的控件组合到一起的面板容器类控件
<!--普通组合框-->
<GroupBox Header="GroupBox Sample" Margin="10" Padding="10">
<StackPanel>
<TextBlock>First name:</TextBlock>
<TextBox />
<TextBlock>Last name:</TextBlock>
<TextBox />
<Button Margin="0,20">Add User</Button>
</StackPanel>
</GroupBox>
<!--自定义标题样式组合框-->
<GroupBox Margin="10" Padding="10">
<GroupBox.Header>
<StackPanel Orientation="Horizontal">
<Image Source="/images/file.png" Margin="3,0" />
<TextBlock FontWeight="Bold">GroupBox Sample</TextBlock>
</StackPanel>
</GroupBox.Header>
<StackPanel>
<TextBlock>First name:</TextBlock>
<TextBox />
<TextBlock>Last name:</TextBlock>
<TextBox />
<Button Margin="0,20">Add User</Button>
</StackPanel>
</GroupBox>
1.5 Calendar
日历控件,显示日历用的。可以使用Viewbox 控件拉伸日历的大小,在默认情况下,Viewbox 会在保持原始宽高比的同时拉伸。通过改变Stretch属性,你能够容易去在两个方向上填充所有空间,通过StretchDirection属性去指定内容应该只被扩展或者缩小。还可以通过DisplayDate属性改变默认的日期。此外SelectionMode属性可以改变选中的模式。Calendar 控件还可以通过使用BlackoutDates集合防止已经被预定的日期被选中。DisplayMode属性则可以设置显示的范围是年或月或日。
<StackPanel>
<!--日历显示-->
<Viewbox Stretch="Fill" StretchDirection="Both">
<Calendar DisplayDate="09.14.2020" SelectionMode="MultipleRange" DisplayMode="Month"/>
</Viewbox>
<!--单选日期-->
<StackPanel Margin="10">
<Calendar Name="cldSample" SelectionMode="MultipleRange" SelectedDate="10.10.2013" />
<Label>Selected date:</Label>
<TextBox Text="{Binding ElementName=cldSample, Path=SelectedDate, StringFormat=d, UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<!--多选日期-->
<StackPanel Margin="10">
<Calendar Name="cldSample2" SelectionMode="MultipleRange" />
<Label>Selected dates:</Label>
<ListBox ItemsSource="{Binding ElementName=cldSample2, Path=SelectedDates}" MinHeight="150" />
</StackPanel>
<!--排除预定日期-->
<StackPanel>
<Viewbox>
<Calendar Name="cldSample3" SelectionMode="MultipleRange">
<Calendar.BlackoutDates>
<CalendarDateRange Start="09.01.2020" End="09.05.2020" />
<CalendarDateRange Start="09.27.2020" End="10.01.2020" />
</Calendar.BlackoutDates>
</Calendar>
</Viewbox>
</StackPanel>
</StackPanel>
// 后置代码设置排除日期
cldSample.BlackoutDates.AddDatesInPast();
cldSample.BlackoutDates.Add(
new CalendarDateRange(DateTime.Today, DateTime.Today.AddDays(1)));
1.6 DatePicker
顾名思义,用来选择日期的控件。SelectedDate 属性设置预选中的日期,DisplayDate属性设置弹出日历显示的默认日期,SelectedDateFormat属性用来设置格式。
<DatePicker SelectedDate="2020-09-14" DisplayDate="2020-01-01"></DatePicker>
<TextBlock></TextBlock>
<DatePicker SelectedDate="2000-12-31" SelectedDateFormat="Long"></DatePicker>
<TextBlock></TextBlock>
<DatePicker Name="dp1">
<DatePicker.BlackoutDates>
<CalendarDateRange Start="2020-09-01" End="2020-09-05" />
<CalendarDateRange Start="2020-09-10" End="2020-09-15" />
</DatePicker.BlackoutDates>
</DatePicker>
1.7 Expander
扩展控件能够隐藏/显示一部分内容,Expander 默认是不会扩展开来的,它是通过IsExpanded 属性初始时扩展。
<!--简单用法-->
<Expander IsExpanded="True">
<TextBlock TextWrapping="Wrap" FontSize="18">
Here we can have text which can be hidden/shown using the built-in functionality of the Expander control.
</TextBlock>
</Expander>
<!--高级用法-->
<Expander Margin="10" ExpandDirection="Down"
Header="Click to show/hide content..."
>
<StackPanel Margin="10">
<DockPanel>
<Image Source="/images/file.png" Width="32" Height="32" DockPanel.Dock="Right" Margin="10"></Image>
<TextBlock TextWrapping="Wrap" FontSize="18">
Did you know that WPF is really awesome? Just enter your e-mail address below and we'll send you updates:
</TextBlock>
</DockPanel>
<TextBox Margin="10">john@doe.org</TextBox>
</StackPanel>
</Expander>
<!--自定义标题-->
<Expander Margin="10">
<Expander.Header>
<DockPanel VerticalAlignment="Stretch">
<Image Source="/images/file.png" Height="16" DockPanel.Dock="Left" />
<TextBlock FontStyle="Italic" Foreground="Green">Click to show/hide content...</TextBlock>
</DockPanel>
</Expander.Header>
<TextBlock TextWrapping="Wrap" FontSize="18">
Here we can have text which can be hidden/shown using the built-in functionality of the Expander control.
</TextBlock>
</Expander>
2. WPF样式
类似HTML中的CSS样式表概念。简单例子如下:
<StackPanel Margin="10">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Gray" />
<Setter Property="FontSize" Value="24" />
</Style>
</StackPanel.Resources>
<TextBlock>Header 1</TextBlock>
<TextBlock>Header 2</TextBlock>
<TextBlock Foreground="Blue">Header 3</TextBlock>
</StackPanel>
2.1 控件范围样式
在本地控件内定义的,只在本地控件中有效
<StackPanel Margin="10">
<StackPanel.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Gray" />
<Setter Property="FontSize" Value="24" />
</Style>
</StackPanel.Resources>
<TextBlock>Header 1</TextBlock>
<TextBlock>Header 2</TextBlock>
<TextBlock Foreground="Blue">Header 3</TextBlock>
</StackPanel>
2.2 窗口范围样式
窗口样式,不明思议,只对本窗口内的 样式有效
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Gray" />
<Setter Property="FontSize" Value="24" />
</Style>
</Window.Resources>
<StackPanel Margin="10">
<TextBlock>Header 1</TextBlock>
<TextBlock>Header 2</TextBlock>
<TextBlock Foreground="Blue">Header 3</TextBlock>
</StackPanel>
2.3 应用程序范围的样式
在APP.xaml中编写样式,则会在应用程序范围内均生效
<Application x:Class="WpfTutorialSamples.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Styles/WindowWideStyleSample.xaml">
<Application.Resources>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Gray" />
<Setter Property="FontSize" Value="24" />
</Style>
</Application.Resources>
</Application>
2.4 字典式样式
<Window.Resources>
<Style x:Key="HeaderStyle" TargetType="TextBlock">
<Setter Property="Foreground" Value="Gray" />
<Setter Property="FontSize" Value="24" />
</Style>
</Window.Resources>
<StackPanel Margin="10">
<TextBlock>Header 1</TextBlock>
<TextBlock Style="{StaticResource HeaderStyle}">Header 2</TextBlock>
<TextBlock>Header 3</TextBlock>
</StackPanel>
3. 触发器
触发器,就是一旦某个条件发生更改,您就可以更改给定属性的值。 触发器有多种形式:属性触发器,事件触发器和数据触发器。 触发器可以在标记中完成通常用后台代码完成的操作。
3.1 属性触发器
<TextBlock Text="Hello, styled world!" FontSize="28" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Foreground" Value="Blue"></Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="Red" />
<Setter Property="TextDecorations" Value="Underline" />
</Trigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
3.2 数据触发器
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<CheckBox Name="cbSample" Content="Hello, world?" />
<TextBlock HorizontalAlignment="Center" Margin="0,20,0,0" FontSize="48">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="No" />
<Setter Property="Foreground" Value="Red" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=cbSample, Path=IsChecked}" Value="True">
<Setter Property="Text" Value="Yes!" />
<Setter Property="Foreground" Value="Green" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
3.3 事件触发器
元素表示的事件触发器主要用于触发动画,以响应被调用的事件。 该实例使用EventTrigger订阅两个事件:MouseEnter和MouseLeave。 当鼠标进入时,会在300毫秒内进行平滑和动画过渡到28像素的FontSize。 当鼠标离开时,FontSize将改回18像素。
<TextBlock Name="lblStyled" Text="Hello, styled world!" FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.300" Storyboard.TargetProperty="FontSize" To="28" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:0.800" Storyboard.TargetProperty="FontSize" To="18" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
3.4 多重触发器
- 多重属性触发器 MultiTrigger
<TextBox VerticalAlignment="Center" HorizontalAlignment="Center" Text="Hover and focus here" Width="150">
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsKeyboardFocused" Value="True" />
<Condition Property="IsMouseOver" Value="True" />
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Background" Value="LightGreen" />
</MultiTrigger.Setters>
</MultiTrigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
- 多重数据触发器 MultiDataTrigger
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<CheckBox Name="cbSampleYes" Content="Yes" />
<CheckBox Name="cbSampleSure" Content="I'm sure" />
<TextBlock HorizontalAlignment="Center" Margin="0,20,0,0" FontSize="28">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Text" Value="Unverified" />
<Setter Property="Foreground" Value="Red" />
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=cbSampleYes, Path=IsChecked}" Value="True" />
<Condition Binding="{Binding ElementName=cbSampleSure, Path=IsChecked}" Value="True" />
</MultiDataTrigger.Conditions>
<Setter Property="Text" Value="Verified" />
<Setter Property="Foreground" Value="Green" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
3.5 制动作画效果
用EnterActions与ExitActions属性结合触发器制造动画效果。
<Border Background="LightGreen" Width="100" Height="100" BorderBrush="Green">
<Border.Style>
<Style TargetType="Border">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Duration="0:0:0.400" To="3" Storyboard.TargetProperty="BorderThickness" />
<DoubleAnimation Duration="0:0:0.300" To="125" Storyboard.TargetProperty="Height" />
<DoubleAnimation Duration="0:0:0.300" To="125" Storyboard.TargetProperty="Width" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<ThicknessAnimation Duration="0:0:0.250" To="0" Storyboard.TargetProperty="BorderThickness" />
<DoubleAnimation Duration="0:0:0.150" To="100" Storyboard.TargetProperty="Height" />
<DoubleAnimation Duration="0:0:0.150" To="100" Storyboard.TargetProperty="Width" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Border.Style>
</Border>