Silverlight自定义控件开发:温度计
2020-12-13 05:36
标签:style blog class c code tar 由于在实际项目中需要实时显示采集到的空气温湿度,土壤温湿度值,需要用比较显眼并且清楚明了的方式来展示,这里我们准备采用温度计的方式来进行。一方面是因为大家都熟悉这个,知道怎么去看;同时,温度计本身也比较好封装。以下就是封装好的效果及其调用代码(水银柱和刻度线都是有动画效果的,看上去比较逼真): 调用代码如下: 由于调用代码相当简单,我就不再这里赘述了,下面着重讲解其实现方式。 首先在Silverlight项目中创建一个用户控件,我们命名为“TemperatureControl.xaml”,然后创建一个“ResData.xaml”资源文件项目,用于放置样式定义。 然后开始对项目进行布局,组织xaml代码,得到的页面显示如下: XAML文件代码如下: 通过第一副图的对比,我们能轻易的知道上图中那些空白的位置放什么东西。 由于在XAML中我采用了Binding来进行数据绑定,那么就展示下我用于数据绑定的类: 上面的代码中,封装了温度计的所有需要的属性,包括刻度值,最大最小范围值,当前值,主题,标题,指标正常与否等。 最后就是具体的事件组织方法: 上面我加了一部分注释,解释的比较清楚了。由于写这个温度计的时候,我们时刻需要测量好屏幕上的水银柱高度和当前值的对应关系,所以里面有比较多的运算,具体的运算方式还希望能够自己推敲。代码我将在下一篇中附上。 Silverlight自定义控件开发:温度计,搜素材,soscw.com Silverlight自定义控件开发:温度计 标签:style blog class c code tar 原文地址:http://www.cnblogs.com/scy251147/p/3737634.html
1: var data = new DataNotify();
2: data.MaxData = 30;
3: data.MinData = -15;
4:
5: data.MinRange = -15;
6: data.MaxRange = 75;
7:
8: data.CurrentData = 40;
9:
10: data.Title = "空气温度";
11: data.Unit = "℃";
12: data.ThemeSet = Theme.Red;
13:
14: var uc = new TemperatureControl(data);
15: uc.Margin = new Thickness(-620, 0, 10, 10);
16: Test.Children.Add(uc);
17:
18:
19: var data1 = new DataNotify();
20: data1.MaxData = 100;
21: data1.MinData = 0;
22: data1.MinRange = 0;
23: data1.MaxRange = 100;
24: data1.CurrentData = 83;
25: data1.Title = "空气湿度";
26: data1.Unit = "%";
27: data1.ThemeSet = Theme.Blue;
28:
29: var uc1 = new TemperatureControl(data1);
30: uc1.Margin = new Thickness(-207, 0, 10, 10);
31: Test.Children.Add(uc1);
32:
33: var data2 = new DataNotify();
34: data2.MaxData = 60;
35: data2.MinData = -10;
36: data2.MinRange = -10;
37: data2.MaxRange = 100;
38: data2.CurrentData = 36;
39: data2.Title = "土壤温度";
40: data2.Unit = "℃";
41: data2.ThemeSet = Theme.Orange;
42:
43: var uc2 = new TemperatureControl(data2);
44: uc2.Margin = new Thickness(213, 0, 10, 10);
45: Test.Children.Add(uc2);
46:
47: var data3 = new DataNotify();
48: data3.MaxData = 60;
49: data3.MinData = -10;
50: data3.MinRange = -10;
51: data3.MaxRange = 100;
52: data3.CurrentData = 36;
53: data3.Title = "土壤湿度";
54: data3.Unit = "%";
55: data3.ThemeSet = Theme.Mo;
56:
57: var uc3 = new TemperatureControl(data3);
58: uc3.Margin = new Thickness(633, 0, 10, 10);
59: Test.Children.Add(uc3);

1: UserControl
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
6: mc:Ignorable="d"
7: x:Class="TinyFrame.Silverlight.TemperatureControl"
8: Loaded="UserControl_Loaded"
9: Width="200" Height="227">
10:
11: Border Style="{StaticResource GridBorder}">
12: Grid x:Name="LayoutRoot" Background="White">
13: Grid.RowDefinitions>
14: RowDefinition Height="30"/>
15: RowDefinition/>
16: Grid.RowDefinitions>
17: Border Grid.Row="0" Style="{StaticResource TopBorder}">
18: TextBlock Style="{StaticResource TxtTitle}" Text="{Binding Title}" />
19: Border>
20: Border Grid.Row="1">
21: Grid>
22: Grid.ColumnDefinitions>
23: ColumnDefinition Width="40"/>
24: ColumnDefinition/>
25: ColumnDefinition/>
26: Grid.ColumnDefinitions>
27: Border Name="bRange" Style="{StaticResource RangeBorder}" BorderBrush="{Binding LineColor}" VerticalAlignment="Bottom">
28: Grid>
29: Grid.RowDefinitions>
30: RowDefinition/>
31: RowDefinition/>
32: Grid.RowDefinitions>
33: TextBlock Grid.Row="0" Style="{StaticResource TxtCommon}" Name="txtMax" Foreground="{Binding lineColor}" VerticalAlignment="Top" >TextBlock>
34: TextBlock Grid.Row="1" Style="{StaticResource TxtCommon}" Name="txtMin" Foreground="{Binding lineColor}" VerticalAlignment="Bottom">TextBlock>
35: Grid>
36: Border>
37: Image Margin="-14,18,0,0" Source="{Binding BgImg}" Grid.Column="1"/>
38: Border Grid.Column="2">
39: Grid>
40: TextBlock Margin="20,40,6,0" Text="{Binding CurrentData}" Foreground="{Binding IsOK}" Style="{StaticResource TxtValue}" >TextBlock>
41: TextBlock Margin="20,65,6,0" Text="{Binding MaxData}" Style="{StaticResource TxtValue}">TextBlock>
42: TextBlock Margin="20,90,6,0" Text="{Binding MinData}" Style="{StaticResource TxtValue}">TextBlock>
43: TextBlock Style="{StaticResource TxtIntro}" Text="当前值:" Margin="-20,40,0,0" Name="i1" />
44: TextBlock Style="{StaticResource TxtIntro}" Text="最大值:" Margin="-20,65,0,0" Name="i2" />
45: TextBlock Style="{StaticResource TxtIntro}" Text="最小值:" Margin="-20,90,0,0" Name="i3" />
46: Grid>
47: Border>
48: Border Style="{StaticResource BorderUnit}" Grid.Column="1" Margin="22,24,0,0">
49: TextBlock Name="t" Text="{Binding Unit}" />
50: Border>
51: Image x:Name="bStep" Style="{StaticResource ImgStep}" Source="{Binding BgStep}" Margin="11,0,0,27" Grid.Column="1" />
52: Canvas Height="120" Background="White" HorizontalAlignment="Left" Margin="24,47,0,0" Name="canvas1" VerticalAlignment="Top" Width="32" OpacityMask="Black" Grid.Column="1" />
53: Grid>
54: Border>
55: Grid>
56: Border>
57: UserControl>
1: public class DataNotify : INotifyPropertyChanged
2: {
3: private double minData = 0; //最小值
4: public double MinData
5: {
6: get
7: {
8: return minData;
9: }
10: set
11: {
12: if (value != minData)
13: {
14: minData = value;
15: Notify("MinData");
16: }
17: }
18: }
19:
20: private double maxData = 1; //最大值
21: public double MaxData
22: {
23: get
24: {
25: return maxData;
26: }
27: set
28: {
29: if (value != maxData)
30: {
31: maxData = value;
32: Notify("MaxData");
33: }
34: }
35: }
36:
37: private double minRange = 0; //刻度最小范围
38: public double MinRange
39: {
40: get { return minRange; }
41: set
42: {
43: if (minRange != value)
44: {
45: minRange = value;
46: Notify("MinRange");
47: }
48: }
49: }
50:
51: private double maxRange = 90; //刻度最大范围
52: public double MaxRange
53: {
54: get { return maxRange; }
55: set
56: {
57: if (maxRange != value)
58: {
59: maxRange = value;
60: Notify("MaxRange");
61: }
62: }
63: }
64:
65: private double currentData; //当前值
66: public double CurrentData
67: {
68: get
69: {
70: return currentData;
71: }
72: set
73: {
74: if (value != currentData)
75: {
76: currentData = value;
77: Notify("CurrentData");
78: }
79: }
80: }
81:
82: private Brush isOK; //指标是否正常
83: public Brush IsOK
84: {
85: get
86: {
87: if (currentData >= minData && currentData
88: return new SolidColorBrush(Colors.Black);
89: else
90: return new SolidColorBrush(Colors.Red);
91: } 92: } 93: 94: private string title; //标题
95: public string Title
96: { 97: get 98: { 99: return title;
100: } 101: set 102: { 103: if (value != title)
104: { 105: title = value;
106: Notify("Title");
107: } 108: } 109: } 110: 111: private string unit; //单位
112: public string Unit
113: { 114: get 115: { 116: return unit;
117: 118: } 119: set 120: { 121: if (value != unit)
122: { 123: unit = value;
124: Notify("Unit");
125: } 126: } 127: } 128: 129: private Theme themeSet;
130: public Theme ThemeSet
131: { 132: get 133: { 134: return themeSet;
135: } 136: set 137: { 138: if (value != themeSet)
139: { 140: themeSet = value;
141: Notify("ThemeSet");
142: } 143: } 144: } 145: 146: private string bgImg; //背景默认值
147: public string BgImg
148: { 149: get 150: { 151: return bgImg;
152: } 153: set 154: { 155: if (value != bgImg)
156: { 157: bgImg = value;
158: Notify("BgImg");
159: } 160: } 161: } 162: 163: private string bgStep; //水银柱块默认值
164: public string BgStep
165: { 166: get 167: { 168: return bgStep;
169: } 170: set 171: { 172: if (value != bgStep)
173: { 174: bgStep = value;
175: Notify("BgStep");
176: } 177: } 178: } 179: 180: private string lineColor; //刻度范围条的颜色
181: public string LineColor
182: { 183: get 184: { 185: return lineColor;
186: } 187: set 188: { 189: if (lineColor != value)
190: { 191: lineColor = value;
192: Notify("LineColor");
193: } 194: } 195: } 196: 197: public event PropertyChangedEventHandler PropertyChanged;
198: 199: public void Notify(string propertyName)
200: { 201: if (PropertyChanged != null)
202: PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
203: } 204: } 1: public partial class TemperatureControl : UserControl
2: {
3: public TemperatureControl(DataNotify dataNotify)
4: {
5: InitializeComponent();
6: this.dataNotify = dataNotify;
7:
8: //绑定数据上下文
9: this.DataContext = dataNotify;
10:
11: //左侧刻度线的最大值最小值
12: double tempMinData = dataNotify.MinData;
13: if (timer == null)
14: timer = new DispatcherTimer();
15: timer.Interval = new TimeSpan(100);
16: timer.Tick += (sender, e) =>
17: {
18: tempMinData++;
19: bRange.Dispatcher.BeginInvoke((Action)(() =>
20: {
21: bRange.Margin = GetThicknessByMaxMin();
22: bRange.Height = (tempMinData - dataNotify.MinData) * THeight / (dataNotify.MaxRange - dataNotify.MinRange);
23: txtMax.Text = tempMinData.ToString("0.0");
24: txtMin.Text = dataNotify.MinData.ToString("0.0");
25: }));
26: if (tempMinData == dataNotify.MaxData)
27: timer.Stop();
28: };
29: timer.Start();
30:
31: //当前值的显示
32: double tempMinRange = dataNotify.MinRange;
33: if (timerStep == null)
34: timerStep = new DispatcherTimer();
35: timerStep.Interval = new TimeSpan(100);
36: timerStep.Tick += (sender, e) =>
37: {
38: tempMinRange++;
39: double value;
40: if (dataNotify.MinRange
41: value = (THeight / (dataNotify.MaxRange - dataNotify.MinRange)) * tempMinRange + (Math.Abs(dataNotify.MinRange)) * (120 / (dataNotify.MaxRange - dataNotify.MinRange));
42: else
43: value = (THeight / (dataNotify.MaxRange - dataNotify.MinRange)) * tempMinRange;
44: if (value
45: value = 0;
46: bStep.Height = value;
47: if (Math.Abs(tempMinRange - dataNotify.CurrentData)
48: { 49: timerStep.Stop(); 50: } 51: }; 52: timerStep.Start(); 53: } 54: 55: private readonly DispatcherTimer timer = null;
56: private readonly DispatcherTimer timerStep = null;
57: public DataNotify dataNotify;
58: 59: private const int THeight = 120; //水银柱高度为120
60: private const int FHeight = 30; //水银球高度为30
61: 62: //动态设置水银柱的Margin属性,以便于适应 带有正负值的场景
63: private Thickness GetThicknessByMaxMin()
64: { 65: double range = dataNotify.MaxRange - dataNotify.MinRange;
66: if (dataNotify.MinRange
67: return new Thickness(0, 0, 0, FHeight + Math.Abs(dataNotify.MinRange)*THeight/range + (dataNotify.MinData) * THeight / range);
68: else
69: return new Thickness(0, 0, 0, FHeight + (dataNotify.MinData) * THeight / range);
70: } 71: 72: private void UserControl_Loaded(object sender, RoutedEventArgs e)
73: { 74: //设置温度计的主题
75: switch (dataNotify.ThemeSet)
76: { 77: case Theme.Red:
78: dataNotify.BgImg = "Image/tem-red.png";
79: dataNotify.BgStep = "Image/step-red.png";
80: dataNotify.LineColor = "Red";
81: break;
82: case Theme.Blue:
83: dataNotify.BgImg = "Image/tem-blue.png";
84: dataNotify.BgStep = "Image/step-blue.png";
85: dataNotify.LineColor = "Blue";
86: break;
87: 88: case Theme.Mo:
89: dataNotify.BgImg = "Image/tem-mo.png";
90: dataNotify.BgStep = "Image/step-mo.png";
91: dataNotify.LineColor = "#00ACAE";
92: break;
93: 94: case Theme.Yellow:
95: dataNotify.BgImg = "Image/tem-yellow.png";
96: dataNotify.BgStep = "Image/step-yellow.png";
97: dataNotify.LineColor = "#849C00";
98: break;
99: 100: case Theme.Orange:
101: dataNotify.BgImg = "Image/tem-orange.png";
102: dataNotify.BgStep = "Image/step-orange.png";
103: dataNotify.LineColor = "#C88600";
104: break;
105: 106: case Theme.Green:
107: dataNotify.BgImg = "Image/tem-green.png";
108: dataNotify.BgStep = "Image/step-green.png";
109: dataNotify.LineColor = "#178A00";
110: break;
111: 112: default:
113: dataNotify.BgImg = "Image/tem-red.png";
114: dataNotify.BgStep = "Image/step-red.png";
115: dataNotify.LineColor = "Red";
116: break;
117: } 118: 119: Draw(dataNotify.MinRange,dataNotify.MaxRange); 120: } 121: 122: //根据用户输入的最大刻度值,最小刻度值,来划刻度线
123: private void Draw(double minRange,double maxRange)
124: { 125: var step = (maxRange - minRange) / 120; 126: Line redLine = new Line();
127: redLine.X1 = 0; 128: redLine.Y1 = 0; 129: redLine.X2 = 0; 130: redLine.Y2 = 120; 131: redLine.StrokeThickness = 1; 132: redLine.Stroke = new SolidColorBrush(Colors.Black);
133: canvas1.Children.Add(redLine); 134: int j = 6;
135: for (int i = 0; i
136: { 137: Line line = new Line();
138: line.X1 = 0; 139: line.Y1 = i * 20; 140: 141: line.X2 =10; 142: line.Y2 = i * 20; 143: 144: TextBlock tb = new TextBlock();
145: tb.Margin = new Thickness(12,i*20-8,0,0);
146: tb.FontSize = 9; 147: tb.Text = (((maxRange - minRange) / 6) * j + minRange).ToString("0");
148: 149: line.StrokeThickness = 1; 150: line.Stroke = new SolidColorBrush(Colors.Black);
151: canvas1.Children.Add(line); 152: canvas1.Children.Add(tb); 153: for (int x = 0; x
154: { 155: Line lineInner = new Line();
156: lineInner.X1 = 0; 157: lineInner.Y1 = (x + 1) * 4; 158: 159: lineInner.X2 = 6; 160: lineInner.Y2 = (x + 1) * 4; 161: 162: lineInner.StrokeThickness = 1; 163: lineInner.Stroke = new SolidColorBrush(Colors.Black);
164: canvas1.Children.Add(lineInner); 165: } 166: 167: j--; 168: } 169: } 170: 171: }