WPF中用户控件和自定义控件如何使用(wpf,开发技术)

时间:2024-04-29 15:36:09 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

介绍

无论是在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所对应的系统主题

WPF中用户控件和自定义控件如何使用

按钮案例

WPF中用户控件和自定义控件如何使用

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中用户控件和自定义控件如何使用的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:小程序中如何处理swiper无法显示图片的问题下一篇:

9 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18