1. Style 的定义
Style是为空间设计外观样式和行为动作。
其中最重要的两种元素是
Setter:设置控件的外观和静态风格
Trigger:设置空间的行为风格。
2. Style的使用
可以直接在xaml文件内部进行设置,但是更多的还是单独抽离为一个 ResourceDictionary进行使用。
在项目目录结构中定义 Style.xaml 文件。
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="{x:Type controls:InputForm}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:InputForm}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="7*" />
<ColumnDefinition Width="auto" />
</Grid.ColumnDefinitions>
<TextBlock
x:Name="PART_TextBlock"
Grid.Column="0"
Height="25"
Margin="0,0,10,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
FontSize="15"
Text="{TemplateBinding MyTextBlockText}"
TextAlignment="Center" />
<TextBox
x:Name="PART_TextBox"
Grid.Column="1"
Height="25"
Margin="0,0,10,0"
VerticalAlignment="Center"
FontSize="14"
Text="{Binding MyTextBoxText, Mode=TwoWay, RelativeSource={RelativeSource Mode=TemplatedParent}}">
<TextBox.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="3" />
</Style>
</TextBox.Resources>
</TextBox>
<Button
x:Name="PART_Button"
Grid.Column="2"
Width="70"
Height="25"
Margin="0,0,30,0"
Command="{TemplateBinding MyButtonCommand}"
Content="{TemplateBinding MyButtonContent}"
Visibility="{TemplateBinding ButtonVisibility}">
<Button.Resources>
<Style TargetType="{x:Type Border}">
<Setter Property="CornerRadius" Value="3" />
</Style>
</Button.Resources>
</Button>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
其中TextBlock空间中, Text="{TemplateBinding MyTextBlockText}"
用到了单向绑定。
3. 对应后台代码
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace DLTool.Controls
{
/// <summary>
/// 抽象出文件夹选择器控件
/// 控件包含一个TextBlock、一个TextBox和一个Button
/// 可以看GetImgFromTextView.xaml中的使用
/// </summary>
public class InputForm : Control
{
/// <summary>
/// 左侧TextBlock的内容,用于显示提示信息
/// </summary>
public string MyTextBlockText
{
get => (string)GetValue(MyTextBlockTextProperty);
set => SetValue(MyTextBlockTextProperty, value);
}
public static readonly DependencyProperty MyTextBlockTextProperty =
DependencyProperty.Register("MyTextBlockText", typeof(string), typeof(InputForm), new PropertyMetadata(""));
/// <summary>
/// 中间TextBox的内容,用于显示文件夹路径
/// </summary>
public string MyTextBoxText
{
get => (string)GetValue(MyTextBoxTextProperty);
set => SetValue(MyTextBoxTextProperty, value);
}
public static readonly DependencyProperty MyTextBoxTextProperty =
DependencyProperty.Register("MyTextBoxText", typeof(string), typeof(InputForm),
new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
/// <summary>
/// 右边Button的内容,用于显示按钮文字
/// </summary>
public string MyButtonContent
{
get { return (string)GetValue(MyButtonContentProperty); }
set { SetValue(MyButtonContentProperty, value); }
}
public static readonly DependencyProperty MyButtonContentProperty =
DependencyProperty.Register("MyButtonContent", typeof(string), typeof(InputForm), new PropertyMetadata(""));
/// <summary>
/// 按钮的可见性
/// </summary>
public Visibility ButtonVisibility
{
get { return (Visibility)GetValue(ButtonVisibilityProperty); }
set { SetValue(ButtonVisibilityProperty, value); }
}
public static readonly DependencyProperty ButtonVisibilityProperty =
DependencyProperty.Register("ButtonVisibility", typeof(Visibility), typeof(InputForm), new PropertyMetadata(Visibility.Visible));
/// <summary>
/// 右边Button的Command,用于触发选择文件夹的操作
/// </summary>
public ICommand MyButtonCommand
{
get => (ICommand)GetValue(MyButtonCommandProperty);
set => SetValue(MyButtonCommandProperty, value);
}
public static readonly DependencyProperty MyButtonCommandProperty =
DependencyProperty.Register("MyButtonCommand", typeof(ICommand), typeof(InputForm), new PropertyMetadata(null));
static InputForm()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(InputForm),
new FrameworkPropertyMetadata(typeof(InputForm)));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
TextBox textBox = GetTemplateChild("PART_TextBox") as TextBox;
if (textBox != null)
{
// 在 Styles.xmal 里AllowDrop已经设为true了,这里不用设置了
textBox.Drop += TextBox_Drop;
textBox.PreviewDragOver += TextBox_PreviewDragOver;
}
}
private void TextBox_PreviewDragOver(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effects = DragDropEffects.Copy;
}
else
{
e.Effects = DragDropEffects.None;
}
e.Handled = true;
}
private void TextBox_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
if (files != null && files.Length > 0)
{
MyTextBoxText = files[0];
}
}
}
}
}
4. 实际使用
<StackPanel Margin="10,0,0,10">
<local:InputForm
x:Name="txtFolderSelector"
Margin="0,5,0,5"
MyButtonCommand="{Binding OpenDatasetPathCommand}"
MyButtonContent="选择"
MyTextBlockText="数据集位置"
MyTextBoxText="{Binding DatasetPath}" />
<local:InputForm
x:Name="datasetFolderSelector"
Margin="0,5,0,5"
ButtonVisibility="Hidden"
MyTextBlockText="训练集比例(%)"
MyTextBoxText="{Binding TrainDatasetPercent}" />
<Button
x:Name="btnProcess"
Width="100"
Height="30"
Margin="0,5,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Command="{Binding ProcessCommand}"
Content="开始处理"
IsEnabled="{Binding ProcessBtnIsEnabled}">
<Button.Resources>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="3" />
</Style>
</Button.Resources>
</Button>
</StackPanel>
```