WPF中用户控件和自定义控件如何使用
导读:本文共5821.5字符,通常情况下阅读需要19分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: 介绍无论是在WPF中还是WinForm中,都有用户控件(UserControl)和自定义控件(CustomControl),这两种控件都是对已有控件的封装,实现功能重用。但是两者还是有一些区别,本文对这两种控件进行讲解。1.用户控件注重复合控件的使用,也就是多个现有控件组成一个可复用的控件组XAML和后台代码组成,绑定紧密不支持模板重写继承自UserContro... ...
目录
(为您整理了一些要点),点击可以直达。介绍
无论是在WPF中还是WinForm中,都有用户控件(UserControl)和自定义控件(CustomControl),这两种控件都是对已有控件的封装,实现功能重用。但是两者还是有一些区别,本文对这两种控件进行讲解。
1.用户控件
注重复合控件的使用,也就是多个现有控件组成一个可复用的控件组
XAML和后台代码组成,绑定紧密
不支持模板重写
继承自UserControl
2.自定义控件
完全自己实现一个控件,如继承现有控件进行功能扩展,并添加新功能
后台代码和Generic.xaml进行组合
在使用时支持模板重写
继承自Control
用户控件
用户控件比较容易理解,与常见的WPF窗体类似,值得注意一点的地方是内部在使用绑定的时候,需要使用RelativeSource
的方式来绑定,以实现良好的封装。一个简单的案例:
定义用户控件
<UserControlx:Class="WpfApp19.UserControl1"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:local="clr-namespace:WpfApp19"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"d:DesignHeight="450"d:DesignWidth="800"mc:Ignorable="d"><Grid><!--下面绑定都要用RelativeSource作为源--><StackPanel><TextBoxWidth="100"BorderThickness="2"Text="{Bindingvalue,RelativeSource={RelativeSourceAncestorType=UserControl}}"/><ButtonWidth="100"Command="{BindingCommand,RelativeSource={RelativeSourceAncestorType=UserControl}}"Content="Ok"/></StackPanel></Grid></UserControl>
后台代码
//根据需要定义依赖属性//所需要绑定的值publicintvalue{get{return(int)GetValue(valueProperty);}set{SetValue(valueProperty,value);}}publicstaticreadonlyDependencyPropertyvalueProperty=DependencyProperty.Register("value",typeof(int),typeof(UserControl1),newPropertyMetadata(0));//所需要绑定的命令publicICommandCommand{get{return(ICommand)GetValue(CommandProperty);}set{SetValue(CommandProperty,value);}}publicstaticreadonlyDependencyPropertyCommandProperty=DependencyProperty.Register("Command",typeof(ICommand),typeof(UserControl1),newPropertyMetadata(default(ICommand)));//所需要绑定的命令参数publicobjectCommandParemeter{get{return(object)GetValue(CommandParemeterProperty);}set{SetValue(CommandParemeterProperty,value);}}publicstaticreadonlyDependencyPropertyCommandParemeterProperty=DependencyProperty.Register("CommandParemeter",typeof(object),typeof(UserControl1),newPropertyMetadata(0));
使用用户控件
<Windowx:Class="WpfApp19.MainWindow"...xmlns:local="clr-namespace:WpfApp19"Title="MainWindow"Height="450"Width="800"><Grid><local:UserControl1value="{Binding}"Command="{Binding}"/></Grid></Window>
自定义控件
点击添加自定义控件后,会增加一个CustomControl1.cs
文件以及一个Themes
目录,在该目录下有一个Generic.xaml
文件,该文件就是自定义控件的style。我们经常针对某些控件进行编辑模板-创建副本的操作而产生的style,其实就是Generic.xaml中定义的style。另外,有时我们可能遇到一种情况,也就是相同的软件在不同的Windows版本下运行,表现形式可能会不同,甚至某些系统下运行不了,这就是和不同系统下的默认的Theme不同。其实wpf控件找不到自定义的样式时,会从系统获取样式,查找顺序是,先查找所在的程序集,如果程序集定义了ThemeInfo
特性,那么会查看ThemeInfoDictionaryLocation
的属性值,该属性如果是None
则说明没有特定的主题资源,值为SourceAssembly
,说明特定资源定义在程序集内部,值为ExternalAssembly
则说明在外部,如果还是没有找到,则程序会在自身的themes/generic.xaml
中获取,在generic.xaml
中获取的其实就和系统默认样式相关。
不同xaml所对应的系统主题
按钮案例
C#文件
publicclassSwitch:ToggleButton{staticSwitch(){//通过重写Metadata,控件就会通过程序集themes文件夹下的generic.xaml来寻找系统默认样式DefaultStyleKeyProperty.OverrideMetadata(typeof(Switch),newFrameworkPropertyMetadata(typeof(Switch)));}}
Themes文件夹下的Generic.xaml文件
注意在该文件中不能有中文,注释也不行
<StyleTargetType="{x:Typelocal:Switch}"><SetterProperty="Template"><Setter.Value><ControlTemplateTargetType="{x:Typelocal:Switch}"><Grid><BorderName="dropdown"Width="{BindingRelativeSource={RelativeSourceSelf},Path=ActualHeight}"Margin="-23"CornerRadius="{BindingRelativeSource={RelativeSourceSelf},Path=ActualHeight}"Visibility="Collapsed"><Border.Background><RadialGradientBrush><GradientStopOffset="1"Color="Transparent"/><GradientStopOffset="0.7"Color="#5500D787"/><GradientStopOffset="0.59"Color="Transparent"/></RadialGradientBrush></Border.Background></Border><BorderName="bor"Width="{BindingRelativeSource={RelativeSourceSelf},Path=ActualHeight}"Background="Gray"BorderBrush="DarkGreen"BorderThickness="5"CornerRadius="{BindingRelativeSource={RelativeSourceSelf},Path=ActualHeight}"><BorderName="bor1"Width="{BindingRelativeSource={RelativeSourceSelf},Path=ActualHeight}"Margin="2"Background="#FF00C88C"CornerRadius="{BindingRelativeSource={RelativeSourceSelf},Path=ActualHeight}"/></Border></Grid><ControlTemplate.Triggers><TriggerProperty="IsChecked"Value="True"><Trigger.EnterActions><BeginStoryboard><Storyboard><ColorAnimationStoryboard.TargetName="bor1"Storyboard.TargetProperty="Background.Color"To="White"Duration="0:0:0.5"/><ColorAnimationStoryboard.TargetName="bor"Storyboard.TargetProperty="BorderBrush.Color"To="#FF32FAC8"Duration="0:0:0.5"/><ObjectAnimationUsingKeyFramesStoryboard.TargetName="dropdown"Storyboard.TargetProperty="Visibil<DiscreteObjectKeyFrameKeyTime="0:0:0.3"><DiscreteObjectKeyFrame.Value><Visibility>Visible</Visibility></DiscreteObjectKeyFrame.Value></DiscreteObjectKeyFrame></ObjectAnimationUsingKeyFrames></Storyboard></BeginStoryboard></Trigger.EnterActions><Trigger.ExitActions><BeginStoryboard><Storyboard><ColorAnimationStoryboard.TargetName="bor1"Storyboard.TargetProperty="Background.Color"/><ColorAnimationStoryboard.TargetName="bor"Storyboard.TargetProperty="BorderBrush.Color"/><ObjectAnimationUsingKeyFramesStoryboard.TargetName="dropdown"Storyboard.TargetProperty="Visibil<DiscreteObjectKeyFrameKeyTime="0:0:0.3"><DiscreteObjectKeyFrame.Value><Visibility>Collapsed</Visibility></DiscreteObjectKeyFrame.Value></DiscreteObjectKeyFrame></ObjectAnimationUsingKeyFrames></Storyboard></BeginStoryboard></Trigger.ExitActions></Trigger></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style>
使用自定控件
<Grid><local:SwitchWidth="100"Height="100"/></Grid>
自定义控件中常用的知识点
TemplatePart特性
在自定义控件中,有些控件是需要有名称的以便于调用,如在重写的OnApplyTemplate()方法中得到指定的button。这就要求用户在使用控件时,不能够修改模板中的名称。
//应用该控件时调用publicoverridevoidOnApplyTemplate(){UpButtonElement=GetTemplateChild("UpButton")asRepeatButton;DownButtonElement=GetTemplateChild("DownButton")asRepeatButton;}
所以在类前面使用特性进行标注
[TemplatePart(Name="UpButton",Type=typeof(RepeatButton))][TemplatePart(Name="DownButton",Type=typeof(RepeatButton))]publicclassNumeric:Control{}
视觉状态的定义与调用
自定义控件中可以定义视觉状态来呈现不同状态下的效果。
在xml中定义视觉状态,不同组下的视觉状态是互斥的
<VisualStateManager.VisualStateGroups><VisualStateGroupName="FocusStates"><VisualStateName="Focused"><Storyboard><ObjectAnimationUsingKeyFramesStoryboard.TargetName="FocusVisual"Storyboard.TargetProperty="Visibility"Duration="0"><DiscreteObjectKeyFrameKeyTime="0"><DiscreteObjectKeyFrame.Value><Visibility>Visible</Visibility></DiscreteObjectKeyFrame.Value></DiscreteObjectKeyFrame></ObjectAnimationUsingKeyFrames></Storyboard></VisualState><VisualStateName="Unfocused"/></VisualStateGroup></VisualStateManager.VisualStateGroups>
在C#中对应视觉状态的切换
privatevoidUpdateStates(booluseTransitions){if(IsFocused){VisualStateManager.GoToState(this,"Focused",false);}else{VisualStateManager.GoToState(this,"Unfocused",false);}}
同时可以在后台类中使用特性来标注
[TemplateVisualState(Name="Focused",GroupName="FocusedStates")][TemplateVisualState(Name="Unfocused",GroupName="FocusedStates")]publicclassNumeric:Control{}
其实完全可以使用Trigger来实现该功能
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
WPF中用户控件和自定义控件如何使用的详细内容,希望对您有所帮助,信息来源于网络。