在实际工作中,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. 24.QTableView函数使用,右击菜单实现

    QTableView view(this); QStandardItemModel model(this); /*设置表头水平标题*/ model.setHorizontalHeaderItem(,n ...

  2. 【Zookeeper】windows环境下zookeeper安装

    下载  Apache官方最新版本为:3.4.12 下载地址:https://mirrors.cnnic.cn/apache/zookeeper/zookeeper-3.4.12/ 安装 解压到指定目录 ...

  3. 记录使用Redis和nginx 实现一个简单的负载均衡(FB)

    这两年在博客园看了不少大牛的分享,一直打算能写点什么东西. 之前偶然看见一个利用Redis 当作 Session数据宿主的demo,出处我已经找不到了.后来没事看了看nginx相关的东西.其中负载均衡 ...

  4. 发现一个微博图床API和图片上传代码

    网上寻到一款微博图床的插件,然后顺藤摸瓜找到了原作者的API代码. API文件: <?php /** * 上传图片到微博图床 * @author Youngxj & mengkun &a ...

  5. CSS border-collapse 属性

    表格边框合并: table {  border-collapse:collapse; 边框会合并为一个单一的边框 } ----------------------------------------- ...

  6. BZOJ4559: [JLoi2016]成绩比较(dp 拉格朗日插值)

    题意 题目链接 Sol 想不到想不到.. 首先在不考虑每个人的真是成绩的情况下,设\(f[i][j]\)表示考虑了前\(i\)个人,有\(j\)个人被碾压的方案数 转移方程:\[f[i][j] = \ ...

  7. 使用Redis作为分布式锁的一些注意点

    Redis实现分布式锁 最近看分布式锁的过程中看到一篇不错的文章,特地的加工一番自己的理解: Redis分布式锁实现的三个核心要素: 1.加锁 最简单的方法是使用setnx命令.key是锁的唯一标识, ...

  8. Brute-forced Euclid Distance Transform

    Sepearable 2D EDT, going to extend to 3D in order to calculate the Signed Distance Function(Field) C ...

  9. onmouseover和onmouseenter区别

    onmouseover和onmouseenter都是鼠标进入时触发,onmouseover在所选元素的子元素间切换的时候也触发! <!doctype html><html lang= ...

  10. jsfiddle 使用教程

    最近有许多的Css 3 demo,因此为了方便查阅,就将demo部分放在jsfiddle ,方便日后翻阅. 这是 JSFIDDLE 的官网文档,都是英文,不过对照看还是可以的:官方文档 HTML区域: ...