wpf两个自定义控件

本文最后更新于 2025-11-16 22:10:34

wpf 两个自定义控件

一个是IP控件,一个滑动条。先看下效果图

IPControl

最新版 YE.Control](https://www.nuget.org/packages/YE.Control)

1、实际工作中有时需要设置IP信息,就想着做一个ip控件。效果没有window自带的好,需要通过tab切换。但也能满足使用。废话不多说直接上代码

IPControl.xaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<UserControl x:Class="WpfApp1.IPControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1">

<Viewbox>
<Border>
<DockPanel>
<DockPanel.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="TextAlignment" Value="Center"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Stretch"/>
<Setter Property="MaxLength" Value="3"/>
<Setter Property="Width" Value="30"/>
<Setter Property="Height" Value="25"/>
</Style>
<Style TargetType="{x:Type Label}">
<Setter Property="Content" Value="."/>
</Style>
</DockPanel.Resources>
<TextBox TabIndex="1" GotFocus="TextBoxGotFocus" Text="{Binding Path=FirstIPValue, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:IPControl}}, UpdateSourceTrigger=PropertyChanged}"/>
<Label/>
<TextBox TabIndex="2" GotFocus="TextBoxGotFocus" Text="{Binding Path=SecondIPValue, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:IPControl}}, UpdateSourceTrigger=PropertyChanged}"/>
<Label/>
<TextBox TabIndex="3" GotFocus="TextBoxGotFocus" Text="{Binding Path=ThirdIPValue, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:IPControl}}, UpdateSourceTrigger=PropertyChanged}"/>
<Label/>
<TextBox TabIndex="4" GotFocus="TextBoxGotFocus" Text="{Binding Path=ForthIPValue, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:IPControl}}, UpdateSourceTrigger=PropertyChanged}"/>
</DockPanel>
</Border>
</Viewbox>
</UserControl>
IPControl.xaml.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
public partial class IPControl : UserControl
{
public IPControl()
{
InitializeComponent();
}


#region DependencyProperty

public static readonly DependencyProperty IPAddressProperty =
DependencyProperty.Register("IPAddress", typeof(string), typeof(IPControl), new PropertyMetadata(defaultIP, (d, e) =>
{
if (d is IPControl control)
{
control.UpdateParts(control);
}
}));

public string IPAddress
{
get { return (string)GetValue(IPAddressProperty); }
set { SetValue(IPAddressProperty, value); }
}

#endregion


#region Static Field

private static readonly string defaultIP = "127.0.0.1";

#endregion


#region Field

private string firstIPValue;
private string secondIPValue;
private string thirdIPValue;
private string forthIPValue;

#endregion


#region Property

public string FirstIPValue
{
get { return firstIPValue; }
set
{
if (firstIPValue != value)
{
UpdateIPText(value, 1, ref firstIPValue);
}
}
}

public string SecondIPValue
{
get { return secondIPValue; }
set
{
if (secondIPValue != value)
{
UpdateIPText(value, 0, ref secondIPValue);
}
}
}

public string ThirdIPValue
{
get { return thirdIPValue; }
set
{
if (thirdIPValue != value)
{
UpdateIPText(value, 0, ref thirdIPValue);
}
}
}

public string ForthIPValue
{
get { return forthIPValue; }
set
{
if (forthIPValue != value)
{
UpdateIPText(value, 0, ref forthIPValue);
}
}
}

#endregion


#region Private Method

private void TextBoxGotFocus(object sender, RoutedEventArgs e)
{
InputMethod.Current.ImeState = InputMethodState.Off;
TextBox tb = sender as TextBox;
if (tb.Text.Length != 0)
{
tb.SelectAll();
}
}

private void UpdateIPText(string oldvalue, int minValue, ref string newValue)
{
int.TryParse(oldvalue, out int iValue);
if (iValue < minValue)
{
iValue = minValue;
}
if (iValue > 255)
{
iValue = 255;
}
newValue = iValue.ToString();
IPAddress = GetIPAddress();
}

private string GetIPAddress()
{
string str = "";
if (firstIPValue != null && firstIPValue.Length > 0)
{
str += firstIPValue + ".";
}
else
{
str += "0.";
}
if (secondIPValue != null && secondIPValue.Length > 0)
{
str += secondIPValue + ".";
}
else
{
str += "0.";
}
if (thirdIPValue != null && thirdIPValue.Length > 0)
{
str += thirdIPValue + ".";
}
else
{
str += "0.";
}
if (forthIPValue != null && forthIPValue.Length > 0)
{
str += forthIPValue;
}
else
{
str += "0";
}
return str;
}

private void UpdateParts(IPControl control)
{
if (control.IPAddress == null)
{
control.IPAddress = defaultIP;
}
string[] parts = control.IPAddress.Split('.');
if (parts.Length == 4)
{
control.FirstIPValue = parts[0];
control.SecondIPValue = parts[1];
control.ThirdIPValue = parts[2];
control.ForthIPValue = parts[3];
}
}

#endregion

}

2、控件有4个TextBox、4个Label组成。TextBox显示IP值,Label显示IP数据的“.”。

TextBox绑定依赖属性,设置TabIndex参数,通过Tab按键切换到下一个TextBox。每个TextBox最多输入3位

LightControl

1、前段时间,领导紧急安排一个工作。做一个测试灯光的小软件。与负责灯光同事沟通得知,光源板可同时控制24路灯。也就是说软件界面上需要有24个ScrollBar用来表示灯光亮度,24个Label显示名称。这要是一个一个控件加太慢了,没法做一个自定义空间,可设置显示名称,通过滑动条或者直接设置参数,改变亮度。于是需要一个Label、一个ScrollBar、一个TextBox与ScrollBar关联。

LightControl.xaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<UserControl x:Class="WpfApp1.LightControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1">

<Viewbox>
<Border>
<DockPanel>
<Label Content="{Binding Path=LabelContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:LightControl}}}"
FontSize="17" Width="80" VerticalContentAlignment="Center"/>
<ScrollBar Value="{Binding Path=LightValue, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:LightControl}}}"
Orientation="Horizontal" Height="40" Width="200" Maximum="100" SmallChange="1"/>
<TextBox Text="{Binding Path=LightValue, StringFormat={}{0:F4}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:LightControl}}, UpdateSourceTrigger=PropertyChanged}"
FontSize="17" Width="80" VerticalContentAlignment="Center"/>
</DockPanel>
</Border>
</Viewbox>
</UserControl>
LightControl.xaml.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public partial class LightControl : UserControl
{
public LightControl()
{
InitializeComponent();
}


#region DependencyProperty

public static readonly DependencyProperty LabelContentProperty =
DependencyProperty.Register("LabelContent", typeof(string), typeof(LightControl), new PropertyMetadata("灯光"));

public string LabelContent
{
get { return (string)GetValue(LabelContentProperty); }
set { SetValue(LabelContentProperty, value); }
}


public static readonly DependencyProperty LightValueProperty =
DependencyProperty.Register("LightValue", typeof(double), typeof(LightControl), new PropertyMetadata(1.0));

public double LightValue
{
get { return (double)GetValue(LightValueProperty); }
set { SetValue(LightValueProperty, value); }
}

#endregion


}

2、Label显示名称通过依赖属性由外接传入。

3、ScrollBar的Value属性与TextBox的Text属性绑定同一个依赖属性,可传递到调用者,同时TextBox显示信息设置保留小数点4位。

工作中有时需要自己做一些自定义控件,用来满足不同场景的需求。两个小控件,比较简单,希望此文能提供一些思路给你。


wpf两个自定义控件
https://njit-77.github.io/2019/11/10/wpf两个自定义控件/
作者
njit-77
发布于
2019年11月10日
许可协议