目录
应用场景说明
一、准备中间数据
1、准备数据
2、数据类使用单例类
3、继承
4、最终实现
二、将中间数据绑定到界面控件
三、在不同的地方给中间数据赋值
1、当前界面直接赋值
2、当前界面,不同线程
3、不再当前界面,不在同一线程
注意事项
1、不在同一个线程下的赋值,需要取消线程检查;
Demo下载
应用场景说明
大家好,今天分享一下如何优雅地给WinForm界面控件的Text属性赋值。在编写上位机时,通常需要显示一个设备的监控信息,而一个设备可能有多个值或状态需要在界面上用多个TextBox或ComboBox显示。当多个输入或多个地方需要更改控件的值时,我们需要编写多个控件赋值的代码:
txtValue1.Text = "1111";
txtValue2.Text = "2222";
cmbSwitchState.Text = "打开";
txtValue1.Text = "3333";
txtValue2.Text = "4444";
cmbSwitchState.Text = "关闭";
另外一点就是,当我们需要给控件赋值的操作在别的类库时,例如采用三层架构,将解码赋值写到BLL层,我们是没法调用winform界面下的控件的,自然就无法调用txtValue1.Text给控件赋值。我们可不可以搞一个中间变量tempStr,将txtValue1.Text = tempStr,无论我们在哪给tempStr赋值,当tempStr变化的时候,txtValue1.Text都自动更新呢。要想实现上面功能,共需要三步。
一、准备中间数据
1、准备数据
在解决方案下新建一个Models类库,在Models类库里面添加一个类(DisplayModel),用于存放给界面显示使用的中间数据
2、数据类使用单例类
DispalyModel类的构造使用单例类
3、继承
DisplayModel类需要继承 INotifyPropertyChanged,对这个进行一下封装
然后我们的DisplayModel类再继承封装后的BindingBase类,并实现其中的SetValue方法,这样当DisplayModel类中的数据发生变化时,会通知界面值已经更改
4、最终实现
namespace Models
{
///
/// 用于界面显示的数据
///
public class DisplayModel : BindingBase
{
private readonly static object lockObj = new object();
private static DisplayModel instance = null;
private DisplayModel() { }
public static DisplayModel Instance
{
get
{
if (instance == null)
{
lock (lockObj)
{
if (instance == null)
{
instance = new DisplayModel();
}
}
}
return instance;
}
}
private string _Value1;
private string _Value2;
private string _SwitchState;
private string _CurrentTime;
private string _CurrentUTCTime;
public string Value1 { get => _Value1; set => SetValue(ref _Value1, value); }
public string Value2 { get => _Value2; set => SetValue(ref _Value2, value); }
public string SwitchState { get => _SwitchState; set => SetValue(ref _SwitchState, value); }
public string CurrentTime { get => _CurrentTime; set => SetValue(ref _CurrentTime, value); }
public string CurrentUTCTime { get => _CurrentUTCTime; set => SetValue(ref _CurrentUTCTime, value); }
}
}
namespace Models
{
public abstract class BindingBase : INotifyPropertyChanged
{
protected void SetValue
[CallerMemberName] string propertyName = null)
{
if ((old == null && value != null) || (old != null && !old.Equals(value)))
{
old = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
二、将中间数据绑定到界面控件
新建一个form,添加控件,在form的load事件中将控件的Text属性与DisplayModel类中的数据进行绑定。
//需要先创建DisplayModel的实例
DisplayModel displayModel = DisplayModel.Instance;
txtValue1.DataBindings.Add("Text", displayModel, "Value1");
txtValue2.DataBindings.Add("Text", displayModel, "Value2");
txtCurrentTime.DataBindings.Add("Text", displayModel, "CurrentTime");
cmbSwitchState.DataBindings.Add("Text", displayModel, "SwitchState");
txtCurrentUtcTime.DataBindings.Add("Text", displayModel, "CurrentUTCTime");
三、在不同的地方给中间数据赋值
1、当前界面直接赋值
2、当前界面,不同线程
在form界面加载时创建一个timer,定时事件中给当前时间控件赋值
3、不再当前界面,不在同一线程
注意事项
1、不在同一个线程下的赋值,需要取消线程检查;
否则数据无法更新到界面上,且这种方式的实现不会报错,出现问题很难查找,所以要特别注意。取消线程检查的方法是在form构造函数中添加下面的代码:
CheckForIllegalCrossThreadCalls = false;
Demo下载
https://download.csdn.net/download/weixin_33376883/88065193
精彩链接
发表评论