WPF自定义控件第一
前期一个小任务需要实现一个类似含步骤进度条的控件。虽然对于XAML的了解还不是足够深入,还是摸索着做了一个。这篇文章介绍下实现这个控件的步骤,最后会放出代码。还请高手们给出更好的思路。同时也希望这里的思路能给同道中人一些帮助。话不多说,开始正题。
实现中的一些代码采用了网上现有的方案,代码中通过注释标记了来源,再次对代码作者一并表示感谢。
首先放一张最终效果图。
节点可以被点击
控件会根据绑定的集合数据生成一系列节点,根据集合中的数据还可以按比例放置节点的位置。
节点的实体代码如下:
public class FlowItem { public FlowItem() { } public FlowItem(int id, string title,double offsetRate) { Id = id; Title = title; OffsetRate = offsetRate; } public int Id { get; set; } public string Title { get; set; } public double OffsetRate { get; set; } }其中三个属性分别代表了节点的编号,标题和偏移量(用来确定节点在整个条中的位置)。
控件的实现忘了很久以前在哪看到过一句话,说设计WPF控件时不一定按照MVVM模式来设计,但一定要确保设计的控件可以按照MVVM模式来使用。本控件也是本着这么目标来完成。
控件实现为TemplatedControl,个人认为这种方式更为灵活,做出来的控件可复用度更高。反之UserControl那种组合控件的方式更适用于一个项目内复用的需要。
遵循一般的原则,,我们将控件单独放于一个项目中。在TemplatedControl项目中,“模板”即XAML内容一般都放置在一个名为Generic.xaml文件中,这个文件应该放置在解决方案Themes文件夹下。
如果要使用Themes/Generic.xaml这个默认的模板样式地址,要保证AssemblyInfo.cs中如下语句:
[assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)]另外也不要试图修改Themes/Generic.xaml这个文件位置了。虽然据说是可以改,但不知道会不会有潜在问题。RoR流行时常说“约定大于配置”,就把这个路径当作一个约定就好了。
一般来说控件的模板也不宜直接放到Generic.xaml而是每个控件都定义到一个单独的xaml文件,然后在Generic中用如下方式进行引用。这样可以有效的防止Generic.xaml文件变的过大,也可以更利于项目模板的查找和修改(直接定位到相关文件即可,博主常用Ctrl+T键定位文件,也不知道这个是VS的功能还是Resharper的功能)。
<ResourceDictionary Source="/Zq.Control;component/Flow/FlowControl.xaml"></ResourceDictionary>这样控件的模板就可以移入FlowControl.xaml中,接着我们就看一下这里面控件模板的定义:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib" xmlns:flow="clr-namespace:Zq.Control.Flow"> <flow:MultiThicknessConverter x:Key="FlowMultiThicknessConverter"></flow:MultiThicknessConverter> <flow:MultiWidthAnimationConverter x:Key="FlowMultiWidthAnimationConverter"></flow:MultiWidthAnimationConverter> <system:Double x:Key="FlowDoubleZero">0</system:Double> <Duration x:Key="FlowDuration">0:0:1.5</Duration> <Style TargetType="{x:Type flow:FlowControl}"> <Setter Property="NodeWidth" Value="30"></Setter> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type flow:FlowControl}"> <Grid VerticalAlignment="Top"> <Grid.Triggers> <EventTrigger RoutedEvent="SizeChanged"> <BeginStoryboard> <Storyboard > <DoubleAnimation Storyboard.TargetName="Bar" Storyboard.TargetProperty="Tag" From="0" To="1" Duration="{StaticResource FlowDuration}"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Grid.Triggers> <Rectangle x:Name="Bar" Panel.ZIndex="0" StrokeThickness="0" Fill="#61d0b3" HorizontalAlignment="Left" VerticalAlignment="Top" Height="{TemplateBinding BarHeight}"> <Rectangle.Margin> <MultiBinding Converter="{StaticResource FlowMultiThicknessConverter}"> <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="BarMarginLeft"></Binding> <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="BarMarginTop"></Binding> <Binding RelativeSource="{RelativeSource TemplatedParent}" Path="BarMarginLeft"></Binding> <Binding Source="{StaticResource FlowDoubleZero}"></Binding> </MultiBinding> </Rectangle.Margin> <Rectangle.Tag> <system:Double>0.0</system:Double> </Rectangle.Tag> <Rectangle.Width> <MultiBinding Converter="{StaticResource FlowMultiWidthAnimationConverter}"> <Binding Path="ShadowWidth" RelativeSource="{RelativeSource TemplatedParent}" /> <Binding Path="Tag" RelativeSource="{RelativeSource Self}" /> </MultiBinding> </Rectangle.Width> </Rectangle> <ItemsPresenter /> </Grid> </ControlTemplate> </Setter.Value> </Setter> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <flow:FlowControlPanel AnimationDuration="{StaticResource FlowDuration}" /> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>这个xaml文件的根节点是ResourceDictionary,表示其中内容是各种资源:样式,模板等等..
最开始的部分定义了模板中用到的一些Conveter及常量值。
温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/67830.html
- 上一篇:报表引擎API开发入门
- 下一篇:Win32编程笔记