基于WPF实现步骤控件的示例代码
wpF 实现步骤控件
框架使用.NET40
;
Visual Studio 2019
;
Step
继承 ItemsControl
使用 Grid
嵌套 ProgressBar
和 ItemsPresenter
.
ProgressBar
用来当作步骤后面的线条,宽等于控件的(ActualWidth / Items.Count) * (Items.Count - 1)
,Maximum = Items.Count - 1
。ItemsPresenter
用来展示步骤Item
。
ItemsPanel - ItemsPanelTemplathttp://www.devze.come - UniformGrid Rows="1"
横向展示,UniformGrid Columns="1"
可以控制竖向显示,只不过需要重新自定义 ItemContainerStyle
的样式。
然后创建 StepItem
继承 ContentControl
增加两个属性 Index
用来记录当前是步骤 与 State
记录状态 (等待中、进行中、已完成)。
因为继承了 ContentControl
所以可以在使用时指定 Content
显示内容,在每个步骤下方显示。
实现代码
1) Step.xaml
代码如下:
<ResourceDictionaryXMLns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:po="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options" xmlns:controls="clr-namespace:WPFDevelopers.Controls" xmlns:converts="clr-namespace:WPFDevelopers.Converts"> <ResourceDictionary.MergedDictionaries> <ResourceDictionarySource="Basic/ControlBasic.xaml"/> </ResourceDictionary.MergedDictionaries> <converts:IndexConverterx:Key="IndexConverter"/> <Stylex:Key="DefaultStepItem"TargetType="{x:Typecontrols:StepItem}" BasedOn="{StaticResourceControlBasicStyle}"> <SetterProperty="BorderThickness"Value="1"/> <SetterProperty="Template"> <Setter.Value> <ControlTemplateTargetType="{x:Typecontrols:StepItem}"> <StackPanel> <controls:SmallPanel> <Ellipse Width="45" Height="30" Fill="{DynamicResourceWindowForegroundColorBrush}" HorizontalAlignment="Center"/> <Border Background="{TemplateBindingBackground}" HorizontalAlignment="Center" CornerRadius="15" BorderThickness="{TemplateBindingBorderThickness}" BorderBrush="{TemplateBindingBorderBrush}" Height="30" Width="30"> <controls:SmallPanel> <TextblockForeground="{TemplateBindingForeground}" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="{TemplateBindingFontSize}" Text="{BindingRelativeSource={RelativeSourceFindAncestor,AncestorType={x:Typecontrols:StepItem}},Converter={StaticResourceIndexConverter}}" Name="PART_Index"/> <PathData="{StaticResourcePathComplete}" Fill="{TemplateBindingForeground}" Stretch="Uniform" Width="12" Height="12" Name="PART_PathComplete" Visibility="Collapsed"/> </controls:SmallPanel> </Border> </controls:SmallPanel> <ContentPresenterHorizontalAlignment="Center" TextElement.FontWeight="Black" ContentTemplate="{BindingItemTemplate,RelativeSource={RelativeSourceAncestorType=controls:Step}}" TextElement.Foreground="{DynamicResourceRegularTextSolidColorBrush}" Margin="0,6,0,0"/> </StackPanel> <ControlTemplate.Triggers> <TriggerProperty="Status"Value="Waiting"> <SetterProperty="Foreground"Value="{DynamicResourcePrimaryTextSolidColorBrush}"/> <SetterProperty="Vpythonisibility"TargetName="PART_PathComplete"Value="Collapsed"/> <SetterProperty="Visibility"TargetName="PART_Index"Value="Visible"/> <SetterProperty="Background"Value="{DynamicResourceBaseSolidColorBrush}"/> </Trigger> <TriggerProperty="Status"Value="InProgress"> <SetterProperty="Foreground"Value="{DynamicResourceDefaultBackgroundSolidColorBrush}"/> <SetterProperty="Visibility"TargetName="PART_PathComplete"Value="Collapsed"/> <SetterProperty="Visibility"TargetName="PART_Index"Value="Visible"/> <SetterProperty="Background"Value="{DynamicResourcePrimaryNormalSolidColorBrush}"/> </Trigger> <TriggerProperty="Status"Value="Complete"> <SetterProperty="BorderBrush"Value="{DynamicResourceDefaultBackgroundSolidColorBrush}"/> <SetterProperty="Background"Value="{DynamicResourceDefaultBackgroundSolidColorBrush}"/> <SetterProperty="Visibility"TargetName="PART_PathComplete"Value="Visible"/> <SetterProperty="Visibility"TargetName="PART_Index"Value="Collapsed"/> <SetterProperty="Foreground"Value="{DynamicResourcePrimaryNormalSolidColorBrush}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> <Stylex:Key="DefaultStep"TargetType="{x:Typecontrols:Step}" BasedOn="{StaticResourceControlBasicStyle}"> <SetterProperty="ItemContainerStyle"Value="{StaticResourceDefaultStepItem}"/> <SetterProperty="VerticalContentAlignment"Value="Top"/> <SetterProperty="HorizontalContentAlignment"Value="Center"/> <SetterProperty="Template"> <Setter.Value> <ControlTemplateTargetType="{x:Typecontrols:Step}"> <controls:SmallPanel> <ProgressBarx:Name="PART_ProgressBar" Margin="0,18" Height="1" Value="{BindingStepIndex,RelativeSource={RelativeSourceAncestorType=controls:Step}}" VerticalAlignment="{TemplateBindingVerticalContentAlignment}" HorizontalAlignment="{TemplateBindingHorizontalContentAlignment}"/> <ItemsPresenter/> </controls:SmallPanel> </ControlTemplate> </Setter.Value> </Setter> <SetterProperty="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <UniformGridRows="1"/> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style> <StyleTargetType="{x:Typecontrols:StepItem}"BasedOn="{StaticResourceDefaultStepItem}"/> <StyleTargetType="{x:Typecontrols:Step编程客栈}"BasedOn="{StaticResourceDefaultStep}"/> </ResourceDictionary>
2) Step.cs
代码如下:
usingSystem; usingSystem.Windows; usingSystem.Windows.Controls; usingSystem.Windows.Controls.Primitives; usingSystem.Windows.Media; namespaceWPFDevelopers.Controls { [TemplatePart(Name=ProgressBarTemplateName,Type=typeof(ProgressBar))] publicclassStep:ItemsControl { privateconststringProgressBarTemplateName="PART_ProgressBar"js; privateProgressBar_progressBar; publicintStepIndex { get=>(int)GetValue(StepIndexProperty); set=>SetValue(StepIndexProperty,value); } publicstaticreadonlyDependencyPropertyStepIndexProperty=DependencyProperty.Register( "StepIndex",typeof(int),typeof(Step),newPropertyMetadata(0,OnStepIndexChanged)); privatestaticvoidOnStepIndexChanged(DependencyObjectd,DependencyPropertyChangedEventArgse) { varstep=(Step)d; varstepIndex=(int)e.NewValue; step.UpdateStepItemState(stepIndex); } voidUpdateStepItemState(intstepIndex) { varcount=Items.Count; if(count<=0)return; if(stepIndex>=count) { StepIndex--; return; } if(stepIndex<0) { StepIndex++; return; } for(vari=0;i<stepIndex;i++) { if(ItemContainerGenerator.ContainerFromIndex(i)isStepItemstepItem) stepItem.Status=Status.Complete; } if(ItemContainerGenerator.ContainerFromIndex(stepIndex)isStepItemitemInProgress) itemInProgress.Status=Status.InProgress; for(vari=stepIndex+1;i<Items.Count;i++) { if(ItemContainerGenerator.ContainerFromIndex(i)isStepItemstepItem) stepItem.Status=Status.Waiting; } } publicoverridevoidOnApplyTemplate() { base.OnApplyTemplate(); _progressBar=GetTemplateChild(ProgressBarTemplateName)ASProgressBar; } protectedoverridevoidOnRender(DrawingContextdrawingContext) { base.OnRender(drawingContext); varcount=Items.Count; if(_progressBar==null||count<=0)return; _progressBar.Maximum=count-1; _progressBar.Value=StepIndex; _progressBar.Width=(ActualWidth/count)*(count-1); } protectedoverrideboolIsItemItsOwnContainerOverride(objectitem) { returnitemisStepItem; } protectedoverrideDependencyObjectGetContainerForItemOverride() { returnnewStepItem(); } publicStep() { ItemContainerGenerator.StatusChanged+=ItemContainerGenerator_StatusChanged; } publicvoidNext() { StepIndex++; } publicvoidPrevious() { StepIndex--; } privatevoidItemContainerGenerator_StatusChanged(objectsender,EventArgse) { if(ItemContainerGenerator.Status==GeneratorStatus.ContainersGenerated) { varcount=Items.Count; if(count<=0)return; UpdateStepItemState(StepIndex); } } } }
3) StepItem.cs
代码如下:
usingSystem.Windows; usingSystem.Windows.Controls; namespaceWPFDevelopers.Controls { publicclassStepItem:ContentControl { publicstaticreadonlyDependencyPropertyIndexProperty=DependencyProperty.Register( "Index",typeof(int),typeof(StepItem),newPropertyMetadata(-1开发者_开发学习)); publicintIndex { get=>(int)GetValue(IndexProperty); internalset=>SetValue(IndexProperty,value); } publicstaticreadonlyDependencyPropertyStatusProperty=DependencyProperty.Register( "Status",typeof(Status),typeof(StepItem),newPropertyMetadata(Status.Waiting)); publicStatusStatus { get=>(Status)GetValue(StatusProperty); internalset=>SetValue(StatusProperty,value); } } }
4) Status.cs
代码如下:
namespaceWPFDevelopers.Controls { ///<summary> ///状态值 ///</summary> publicenumStatus { ///<summary> ///等待中 ///</summary> Waiting, ///<summary> ///正在进行中 ///</summary> InProgress, ///<summary> ///完成 ///</summary> Complete } }
5) StepExample.xaml
代码如下:
<UserControlx:Class="WPFDevelopers.Samples.ExampleViews.StepExample" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls" xmlns:wd="https://github.com/WPFDevelopersOrg/WPFDevelopers" xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews" mc:Ignorable="d" d:DesignHeight="450"d:DesignWidth="800"> <controls:CodeViewer> <StackPanelVerticalAlignment="Center"> <UniformGridColumns="2"Name="PART_UniformGrid"> <wd:Stepx:Name="PART_Step"StepIndex="{BindingProgress}"> <wd:StepItemContent="填写账号"/> <wd:StepItemContent="身份验证"/> <wd:StepItemContent="设置新密码"/> <wd:StepItemContent="完成"/> </wd:Step> <wd:StepStepIndex="0"ItemsSource="{BindingSteps}"> </wd:Step> </UniformGrid> <StackPanelOrientation="Horizontal" VerticalAlignm编程ent="Center" HorizontalAlignment="Center" Margin="10"> <ButtonContent="上一步"Command="{BindingPreviousCommand}" CommandParameter="{BindingElementName=PART_UniformGrid}" Style="{StaticResourcePrimaryButton}"/> <ButtonContent="下一步"Command="{BindingNextCommand}" CommandParameter="{BindingElementName=PART_UniformGrid}" Style="{StaticResourcePrimaryButton}"/> </StackPanel> </StackPanel> <controls:CodeViewer.SourceCodes> <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/StepExample.xaml" CodeType="Xaml"/> <controls:SourceCodeModel CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/StepExample.xaml.cs" CodeType="CSharp"/> </controls:CodeViewer.SourceCodes> </controls:CodeViewer> </UserControl>
6) StepExample.xaml.cs
代码如下:
usingSystem; usingSystem.Collections.ObjectModel; usingSystem.Linq; usingSystem.Windows.Controls; usingSystem.Windows.Controls.Primitives; usingSystem.Windows.Input; usingWPFDevelopers.Controls; usingWPFDevelopers.Samples.Helpers; namespaceWPFDevelopers.Samples.ExampleViews { ///<summary> ///StepExample.xaml的交互逻辑 ///</summary> publicpartialclassStepExample:UserControl { publicObservableCollection<string>Steps { get; set; } publicStepExample() { InitializeComponent(); Steps=newObservableCollection<string>(); Steps.Add("Step1"); Steps.Add("Step2"); Steps.Add("Step3"); Steps.Add("Step4"); this.DataContext=this; } publicICommandNextCommand=>newRelayCommand(newAction<object>((sender)=> { varuniformGrid=senderasUniformGrid; if(uniformGrid==null)return; foreach(varstepinuniformGrid.Children.OfType<Step>()) step.Next(); })); publicICommandPreviousCommand=>newRelayCommand(newAction<object>((sender)=> { varuniformGrid=senderasUniformGrid; if(uniformGrid==null)return; foreach(varstepinuniformGrid.Children.OfType<Step>()) step.Previous(); })); } }
效果图
以上就是基于WPF实现步骤控件的示例代码的详细内容,更多关于WPF步骤控件的资料请关注我们其它相关文章!
精彩评论