WPF 中要写一个自己的控件,可以选择“用户控件”(派生自UserControl)或“自定义控件”(派生自Control类或其子类)。用户控件就像创建一个窗体或页面一样,有一个XAML文件和对应的.cs隐藏文件。如果是添加自定义控件,会看到一个.cs 文件和 themes\generic.xaml。这里写一个小例子,说明下WPF自定义控件的开发过程。
实现一个可删除的Label, 添加自定义控件:RemoveLabel
[TemplatePart(Name = "PART_LableButton", Type = typeof(Panel))]
public class RemoveLabel: Control
{
private Button btnLableButton = null;
public static readonly DependencyProperty DisplayTextProperty = DependencyProperty.Register("DisplayText", typeof(string), typeof(RemoveLable), new PropertyMetadata(string.Empty));
/// <summary>
/// 显示文本
/// </summary>
public string DisplayText
{
get { return (string)GetValue(DisplayTextProperty); }
set { SetValue(DisplayTextProperty, value); }
}
static RemoveLable()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(RemoveLable), new FrameworkPropertyMetadata(typeof(RemoveLable)));
}
#region 自定义Command
public ICommand RemoveCommand
{
get { return (ICommand)GetValue(RemoveCommandProperty); }
set { SetValue(RemoveCommandProperty, value); }
}
public static readonly DependencyProperty RemoveCommandProperty =
DependencyProperty.Register("RemoveCommand", typeof(ICommand), typeof(RemoveLable), new PropertyMetadata(default(ICommand)));
public object CommandParameter
{
get { return (object)GetValue(CommandParameterProperty); }
set { SetValue(CommandParameterProperty, value); }
}
public static readonly DependencyProperty CommandParameterProperty =
DependencyProperty.Register("CommandParameter", typeof(object), typeof(RemoveLable), new PropertyMetadata(default(object)));
public IInputElement CommandTarget { get; set; }
#endregion
#region Override Methods
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
btnLabelButton = GetTemplateChild("PART_LableButton") as Button;
if (btnLabelButton != null)
{
btnLabelButton.Click += BtnLableButton_Click; ;
}
}
/// <summary>
/// 删除按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void BtnLableButton_Click(object sender, RoutedEventArgs e)
{
if (this.RemoveCommand != null)
{
this.RemoveCommand.Execute(CommandParameter);
}
}
#endregion
}
RemoveLabel 简单的样式:
<Style TargetType="{x:Type local:RemoveLable}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:RemoveLable}">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="txtBlockSourceName" MaxWidth="200" VerticalAlignment="Center" ToolTip="{Binding Text, RelativeSource={RelativeSource Mode=Self}}"
HorizontalAlignment="Left" TextTrimming="CharacterEllipsis" Text="{TemplateBinding DisplayText}"/>
<Button x:Name="PART_LableButton" Style="{StaticResource MaterialDesignIconButton}" ToolTip="变更数据源" VerticalAlignment="Center">
<materialDesign:PackIcon Kind="FileDocumentEditOutline" />
</Button>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
用法:
<DataGrid x:Name="gridList" ItemsSource="{Binding Devices,UpdateSourceTrigger=PropertyChanged}" CanUserSortColumns="False"
Canvas.Left="0" CanUserAddRows="False" AutoGenerateColumns="False" HeadersVisibility="Column">
<DataGrid.Resources>
<ulitiy:BindingProxy x:Key="DataContextProxy" Data="{Binding}"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn Width="*" Header="数据源" Visibility="{Binding Data.IsViewLoad, Source={StaticResource DataContextProxy},UpdateSourceTrigger=PropertyChanged, Converter={StaticResource functionCvt}, ConverterParameter=LaserList_DataSource_Select}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<local:RemoveLable x:Name="txtBlockSourceName" Height="30" Grid.Column="0"
RemoveCommand="{Binding Data.SelectDataSourceCommand, Source={StaticResource DataContextProxy}}"
CommandParameter="{Binding .}"
HorizontalAlignment="Left" DisplayText="{Binding DataSourceName}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>