WPF自定义控件(四)の自定义控件

在实际工作中,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自定义控件(五)の控件分类

时间: 2025-01-04 22:31:10

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

常用的自定义控件四(QuickBarView)

常用的自定义控件四(QuickBarView) 自定义View 通讯录字母快速索引 在Android日常开发中,我们经常在联系人界面看到一些字母导航栏,点击字母的时候,会根据汉字的首拼音来查找是否存在相应的item,这种效果很常见,几乎所有涉及到通讯的都会用到,包括qq,微信,微博等,今天我为大家带来的就是这种自定义控件 废话不多说 ,大家先来看一下实际的效果 效果图一 转载请注明原博客地址:http://blog.csdn.net/gdutxiaoxu/article/details/5180

WPF 精修篇 自定义控件

原文:WPF 精修篇 自定义控件 自定义控件 因为没有办法对界面可视化编辑 所以用来很少 现在实现的是 自定义控件的 自定义属性 和自定义方法 用VS 创建自定义控件后 会自动创建 Themes 文件夹和 Generic.xaml 还有自定义的类 这边是SeachControl Gneneric <Style TargetType="{x:Type local:SeachControl}"> <Setter Property="Template"&

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

原文:WPF案例 (四) 模拟Windows7桌面任务栏 这个程序模彷了Windows7的桌面任务栏,当在桌面上双击某个快捷方式时,将打开一个新的子界面,并且在任务栏里创建一个链接到此界面的任务栏图标,将鼠标移动到任务栏上的图标时,将Popup出界面的实时图像缩略图,单击任务栏图标时,可让界面最大化或最小化,界面如下所示,源码从这里下载 做这个任务栏界面缩略图时,使用VisualBrush将子界面的实时图像填充到Rectangle 1  Rectangle emptyRectangle = ne

从PRISM开始学WPF(四)Prism-Module?

原文:从PRISM开始学WPF(四)Prism-Module? 从PRISM开始学WPF(一)WPF? 从PRISM开始学WPF(二)Prism? 从PRISM开始学WPF(三)Prism-Region? 从PRISM开始学WPF(四)Prism-Module? 从PRISM开始学WPF(五)MVVM(一)ViewModel? 从PRISM开始学WPF(六)MVVM(二)Command? 从PRISM开始学WPF(七)MVVM(三)事件聚合器EventAggregator? 0x4Modules

WPF中将四个数字字符串值(比如:&quot;10,10,300,300&quot;)转为Rect

原文:WPF中将四个数字字符串值(比如:"10,10,300,300")转为Rect RectConverter rectConverter = new RectConverter(); string parseString = viewportEntry.Text; if (parseString != null && parseString != string.Empty) { imageBrush.Viewport = (Rect)rectConverter.Co

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

1. 前言 WPF有一个灵活的UI框架,用户可以轻松地使用代码控制控件的外观.例设我需要一个控件在鼠标进入的时候背景变成蓝色,我可以用下面这段代码实现: protected override void OnMouseEnter(MouseEventArgs e) { base.OnMouseEnter(e); Background = new SolidColorBrush(Colors.Blue); } 但一般没人会这么做,因为这样做代码和UI过于耦合,难以扩展.正确的做法应该是使用代码告诉C

WPF使用Winform自定义控件

在WPF的用户控件中使用Winfrom自定义控件的过程: 1.添加引用 WindowsFormsIntegration.dll System.Windows.Forms.dll 2.在要使用WinForm控件的WPF窗体的XAML文件中添加如下内容: xmlns:wf="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" xmlns:wfi ="clr-namespace:System.Windo

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

问题起因:在一个用户控件里放置了1个TreeView垂直顺序放置. 当用户控件中的内容超过面板大小时,滚动条会自动出现 ,但是只有当鼠标指示在右边滚动条的那一条位置时,才支持鼠标滚轴滚动. 点在控件内部时滚轴无效. 问题分析:由于设置了d:designheight,自定义控件的宽高都是随着父容器的变化而变化的,于是我将Height设为较小的固定高度时,发现鼠标停留在控件内容时,滚轮控制滚动条滚动是有效的.这就说明UI上显示的滚动条并非是这个自定义控件的,而是这个自定义控件所在的父容器的,这样也解

Android自定义控件(四)仿网易客户端上拉加载更多

上一篇仿得网页客户端的抽屉模式,这一篇继续,来写一写加载更多这个功能,通过自定义实现加载更多,先上图: 今天实现的就是如图中最下面的20条载入中...这个功能啦! 先来说一下思路: 1.在listview中加入20条载入中的这个布局并隐藏 2.加入OnScrollListener监听,通过监听滚动事件,当滚动到最低端的时候,显示上面的布局 3.通过接口回调实现加载更多的功能 4.加载完数据时,通知listview加载结束,隐藏上面的布局文件 下面直接上代码: 1.在listview中加入20条载

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

onFinishInflate() 当View中所有的子控件 均被映射成xml后触发 onMeasure(int, int) 确定所有子元素的大小 onLayout(boolean, int, int, int, int) 当View分配所有的子元素的大小和位置时触发 onSizeChanged(int, int, int, int) 当view的大小发生变化时触发 onDraw(Canvas) view渲染内容的细节 onKeyDown(int, KeyEvent) 有按键按下后触发 onKe