在实际工作中,WPF提供的控件并不能完全满足不同的设计需求。这时,需要我们设计自定义控件。

这里LZ总结一些自己的思路,特性如下:

  • Coupling
  • UITemplate
  • Behaviour
  • Function Package

下面举例说说在项目中我们经常用到调音台音量条,写一个自定义控件模拟调音台音量条。

自定义控件SingnalLight,实现功能

  • 接收来自外部的范围0~100的数值
  • 实时显示接收数值
  • 数值范围0~50显示绿色,50~85显示黄色,85~100显示红色,没有数值显示褐色
  • 可在父控件上拖拽该控件
public class SingnalLight : ContentControl {
public int ValueA {
get { return (int)GetValue(ValueAProperty); }
set { SetValue(ValueAProperty, value); }
} public SingnalLight() {
this.AllowDrop = true;
} static SingnalLight() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(SingnalLight), new FrameworkPropertyMetadata(typeof(SingnalLight)));
} }

ValueA为接受外部数值的属性

2.复写控件UITemplate

 1  <Style TargetType="{x:Type control:SingnalLight}">
2 <Setter Property="RenderTransform">
3 <Setter.Value>
4 <TranslateTransform X="{Binding Path=X,RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}}}"
5 Y="{Binding Path=Y,RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}}}"/>
6 </Setter.Value>
7 </Setter>
8 <Setter Property="Template">
9 <Setter.Value>
10 <ControlTemplate>
11 <ControlTemplate.Resources>
12 <control:SingnalLightStatusConverter x:Key="colorconverter"></control:SingnalLightStatusConverter>
13 <control:SingnalLightValueConverter x:Key="valueconverter"></control:SingnalLightValueConverter>
14 </ControlTemplate.Resources>
15 <StackPanel>
16 <TextBlock Text="{Binding Path=ValueA,RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}}}"></TextBlock>
17 <TextBlock Text="100"></TextBlock>
18 <Border
19 x:Name="bd1"
20 Height="{Binding Path=LightHeight,RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}}}"
21 SnapsToDevicePixels="True"
22 BorderBrush="Black" BorderThickness="1" Background="Transparent">
23 <Rectangle Fill="{Binding Path=ValueA,
24 RelativeSource={RelativeSource AncestorType={x:Type control:SingnalLight}},
25 Converter={StaticResource ResourceKey=colorconverter}}"
26 VerticalAlignment="Bottom">
27 <Rectangle.Height>
28 <MultiBinding Converter="{StaticResource ResourceKey=valueconverter}">
29 <Binding Path="ValueA" RelativeSource="{RelativeSource AncestorType={x:Type control:SingnalLight}}"></Binding>
30 <Binding Path="Height" ElementName="bd1"></Binding>
31 </MultiBinding>
32 </Rectangle.Height>
33 </Rectangle>
34 </Border>
35 <TextBlock Text="0"></TextBlock>
36 </StackPanel>
37 </ControlTemplate>
38 </Setter.Value>
39 </Setter>
40 </Style>

3.接受值判断,SingnalLight通过实现IValueConverter和Override Arrange & Measure Methods,实现了UI呈现的绑定,

 1     public class SingnalLightStatusConverter : IValueConverter {
2 public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
3 SolidColorBrush result = Brushes.Transparent;
4 if (value.GetType() == typeof(int)) {
5 var color = System.Convert.ToInt32(value);
6 if (color < 50) result = Brushes.Green;
7 else if (color < 85 && color >= 50) result = Brushes.Yellow;
8 else if (color <= 100 && color >= 85) result = Brushes.Red;
9 else result = Brushes.Gray;
10 }
11 return result;
12 }
13
14 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
15 throw new NotImplementedException();
16 }
17 }
18
19 public class SingnalLightValueConverter : IMultiValueConverter {
20 public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
21 double result = 0;
22 if (values[0].GetType() == typeof(int) && values[1].GetType() == typeof(double)) {
23 result = (double)values[1] / 100 * System.Convert.ToDouble(values[0]);
24 }
25 return result;
26 }
27
28 public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture) {
29 throw new NotImplementedException();
30 }
31 }
 
 
1         protected override Size MeasureOverride(Size constraint) {
2 if (ActualHeight > 0) LightHeight = ActualHeight * .7;
3 return base.MeasureOverride(constraint);
4 }
5
6 protected override Size ArrangeOverride(Size arrangeBounds) {
7 return base.ArrangeOverride(arrangeBounds);
8 }
 

4.控件支持拖拽,覆写MouseDown,MouseMove,MouseUp方法。这样写的好处是,如果在父控件的事件中实现Drag,父控件如果有多个对象,这样逻辑会十分混乱。

 
 1         protected override void OnMouseMove(MouseEventArgs e) {
2 base.OnMouseMove(e);
3 if (e.LeftButton == MouseButtonState.Pressed) {
4 _currentPoint = e.GetPosition(this);
5 X += _currentPoint.X - _startPoint.X;
6 Y += _currentPoint.Y - _startPoint.Y;
7 }
8 }
9
10 protected override void OnMouseDown(MouseButtonEventArgs e) {
11 base.OnMouseDown(e);
12 _startPoint = e.GetPosition(this);
13 this.CaptureMouse();
14 }
15
16 protected override void OnMouseUp(MouseButtonEventArgs e) {
17 base.OnMouseUp(e);
18 this.ReleaseMouseCapture();
19 }
 

自定义控件系列博文链接:

WPF自定义控件(一)の控件分类
WPF自定义控件(二)の重写原生控件样式模板
WPF自定义控件(三)の扩展控件
WPF自定义控件(四)の自定义控件
WPF自定义控件(五)の用户控件

WPF自定义控件(四)の自定义控件的更多相关文章

  1. WPF 精修篇 自定义控件

    原文:WPF 精修篇 自定义控件 自定义控件 因为没有办法对界面可视化编辑 所以用来很少 现在实现的是 自定义控件的 自定义属性 和自定义方法 用VS 创建自定义控件后 会自动创建 Themes 文件 ...

  2. wpf 两个自定义控件

    wpf 两个自定义控件 一个是IP控件,一个滑动条.先看下效果图 IPControl 1.实际工作中有时需要设置IP信息,就想着做一个ip控件.效果没有window自带的好,需要通过tab切换.但也能 ...

  3. WPF案例 (四) 模拟Windows7桌面任务栏

    原文:WPF案例 (四) 模拟Windows7桌面任务栏 这个程序模彷了Windows7的桌面任务栏,当在桌面上双击某个快捷方式时,将打开一个新的子界面,并且在任务栏里创建一个链接到此界面的任务栏图标 ...

  4. WPF入门(四)->线形区域Path内容填充之填充图(ImageBrush)

    原文:WPF入门(四)->线形区域Path内容填充之填充图(ImageBrush) 前面我们提到了LinearGradientBrush可以用来画渐变填充图,那么我们同时也可以使用ImageBr ...

  5. WPF入门(四)->线形区域Path内容填充之渐变色(LinearGradientBrush)

    原文:WPF入门(四)->线形区域Path内容填充之渐变色(LinearGradientBrush) 前面我们介绍到,Path对象表示一个用直线或者曲线连接的图形,我们可以使用Path.Data ...

  6. 好玩的WPF第四弹:用Viewport2DVisual3D实现3D旋转效果

    原文:好玩的WPF第四弹:用Viewport2DVisual3D实现3D旋转效果 版权声明:转载请联系本人,感谢配合!本站地址:http://blog.csdn.net/nomasp https:// ...

  7. [WPF自定义控件库] 自定义控件的代码如何与ControlTemplate交互

    1. 前言 WPF有一个灵活的UI框架,用户可以轻松地使用代码控制控件的外观.例设我需要一个控件在鼠标进入的时候背景变成蓝色,我可以用下面这段代码实现: protected override void ...

  8. WPF中关于自定义控件的滚动条鼠标停留在内容上鼠标滚轮滚动无效的问题

    问题起因:在一个用户控件里放置了1个TreeView垂直顺序放置. 当用户控件中的内容超过面板大小时,滚动条会自动出现 ,但是只有当鼠标指示在右边滚动条的那一条位置时,才支持鼠标滚轴滚动. 点在控件内 ...

  9. android自定义控件(四) View中的方法

    onFinishInflate() 当View中所有的子控件 均被映射成xml后触发 onMeasure(int, int) 确定所有子元素的大小 onLayout(boolean, int, int ...

  10. wpf 中的 自定义控件的 binding

    XMl 代码 --------------------------------------------------------------------------------------------- ...

随机推荐

  1. T-SQL基础(三)之子查询与表表达式

    子查询 在嵌套查询中,最外面查询结果集返回给调用方,称为外部查询.嵌套在外部查询内的查询称为子查询,子查询的结果集供外部查询使用. 根据是否依赖外部查询,可将子查询分为自包含子查询和相关子查询.自包含 ...

  2. mongodb "Element '{0}' does not match any field or property of class" 异常的解决方法

    在序列化的对象上增加 [BsonIgnoreExtraElements]

  3. 26.QT-模型视图之自定义委托

    在上一章学习 25.QT-模型视图 后,本章接着学习视图委托 视图委托(Delegate)简介 由于模型负责组织数据,而视图负责显示数据,所以当用户想修改显示的数据时,就要通过视图中的委托来完成 视图 ...

  4. Eclipse中SVN插件的安装和配置(在线安装)

    公司项目中用到了svn来管理项目,然后需要在Eclipse中进行配置.网上参考了很多资料,离线安装的方式装上了,但是导入项目后报错,可能是离线安装包的问题.然后又采用了Eclipse在线安装的方式,总 ...

  5. JavaScript是如何工作的:事件循环和异步编程的崛起 + 5种使用 async/await 更好地编码方式!

    摘要: 深度理解JS事件循环!!! 原文:JavaScript是如何工作的:事件循环和异步编程的崛起+ 5种使用 async/await 更好地编码方式! 作者:前端小智 Fundebug经授权转载, ...

  6. express 对数据库数据增删改查

    接着 http://www.cnblogs.com/cynthia-wuqian/p/6560548.html (1)概念 Schema(属性) :一种以文件形式存储的数 据库模型骨架,不具备数据库的 ...

  7. Linux 进程调度的主要策略

    1.Linux 下进程分为5种类别,分别是停止类.截止类.实时类.公平类.空闲类, 每种类别都有一个运行队列,每次调度时,就是先按照类别优先级排序,再按照每个类别内的最高优先级任务调度运行. 文件:c ...

  8. Python异常处理机制、调试、测试

    类似于Java的try..catch..finally Java的为try_except_finally try: print('try...') r = / print('result:', r) ...

  9. 简单的Array.sort 排序方法

    [排序]sort类    Arrays.sort升序排序 import java.util.Arrays;//导入Arrays类public class menu{ public static voi ...

  10. CSS回顾(常见问题解决)

    一.margin的塌陷解决: BFC (block format context)块级格式化上下文格式 display:inline-block float:left / right overflow ...