开发者

基于WPF实现步骤控件的示例代码

开发者 https://www.devze.com 2023-01-12 10:51 出处:网络 作者: 驚鏵
wpF 实现步骤控件 框架使用.NET40; Visual Studio 2019; Step 继承 ItemsControl 使用 Grid 嵌套 ProgressBar 和 ItemsPresenter.

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 显示内容,在每个步骤下方显示。

基于WPF实现步骤控件的示例代码

实现代码

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实现步骤控件的示例代码的详细内容,更多关于WPF步骤控件的资料请关注我们其它相关文章!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号