C#数据绑定-自动将更改的属性写入标签或文本框
我读了一些关于数据绑定的书,大部分是复杂的东西,比如SQL或任何XAML之类的东西。 我想让我的程序做的就是,如果变量的“值”改变了,就把它写在文本框或标签中。(使用Windows窗体) 到目前为止,我有:C#数据绑定-自动将更改的属性写入标签或文本框,c#,data-binding,windows-forms-designer,C#,Data Binding,Windows Forms Designer,我读了一些关于数据绑定的书,大部分是复杂的东西,比如SQL或任何XAML之类的东西。 我想让我的程序做的就是,如果变量的“值”改变了,就把它写在文本框或标签中。(使用Windows窗体) 到目前为止,我有: namespace DataBinding_Test { public partial class Form1 : Form { BindingSource bs = new BindingSource(); Class1 test = new Class1
namespace DataBinding_Test
{
public partial class Form1 : Form
{
BindingSource bs = new BindingSource();
Class1 test = new Class1();
public Form1()
{
InitializeComponent();
test.name = "Hello";
bs.DataSource = test;
label1.DataBindings.Add(new Binding("Text", bs, "name", false, DataSourceUpdateMode.OnPropertyChanged));
}
private void button1_Click(object sender, EventArgs e)
{
test.name = textBox1.Text;
}
}
}
Class1只有一个公共属性名。启动时,标签1将显示我的“Hello”字符串。然后单击按钮上的“名称”属性将更改。在调试时,我看到“bs”的实际数据源包含新的属性值,但标签不会显示任何内容
有什么真正简单的方法可以做到这一点吗
回溯是:定期通过RS232轮询传感器数据。如果一个传感器的值发生变化,我想在标签或文本框中显示。现在,backroundthreaded计时器需要调用和填充来访问GUI线程;本以为使用数据绑定会更容易,但似乎并非如此:P
感谢所有人,伟大的网站,伟大的工作!:) 我不确定这是否是您想要的,但是您可以使用control.Text属性将变量包含的任何内容写入文本框或标签
textBox1.Text ="Some other Text"
或
你为什么要使用数据绑定?这样做更容易。为了让代码正常工作,应该在绑定类中实现接口。没有它,您的绑定根本不知道何时发生更改。在那里,您应该执行逻辑,根据该逻辑,当类中发生更改时(setter部分)会通知订阅者,以及发生了什么更改(PropertyChangedEventArgs)。请参见您的类的示例:
class Class1: INotifyPropertyChanged
{
private string name = "";
public string Name
{
get { return name; }
set { name = value; NotifyPropertyChanged(); }
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged()
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Name"));
}
}
}
并将绑定中的属性名称从“name”更改为“name”:
label1.DataBindings.Add(new Binding("Text", bs, "Name", false, DataSourceUpdateMode.OnPropertyChanged));
另一种无需实现INotifyPropertyChanged的方法
class Class1
{
private string name;
public string Name
{
get { return name; }
set
{
//Check if you are assigning the same value. Depends on your business logic
//here is the simplest check
if (Equals(name, value))
return;
name = value;
OnNameChanged();
}
public event EventHandler NameChanged;
protected virtual void OnNameChanged()
{
var handler = NameChanged;
if (handler != null)
handler(this, EventArgs.Empty);
}
}
}
诀窍是让事件的名称由属性名称和
更改的后缀组合而成,并在属性值更改时将其提升我为此创建了一个扩展方法,希望与大家分享
// create winforms project on form1 drag a textbox (testbox1)
// and a button (button1) with a button click event handler
// this updates the textbox when the button is clicked
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
MyClass Myobj = new MyClass();
public Form1()
{
InitializeComponent();
/* propertyname, datasource, datamember */
textBox1.DataBindings.Add("Text", Myobj, "Unit");
}
public class MyClass : INotifyPropertyChanged
{
private int unit = 3;
/* property change event */
public event PropertyChangedEventHandler PropertyChanged;
public int Unit
{
get
{
return this.unit;
}
set
{
if (value != this.unit)
{
this.unit = value;
NotifyPropertyChanged("Unit");
}
}
}
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
private void button1_Click(object sender, EventArgs e)
{
Myobj.Unit += 4;
}
}
}
用法
private void Form1_Load(object sender, EventArgs e)
{
ResultLabel.Bind(NameTextBox);
WarningLabel.Bind(NameTextBox,i => i.Length == 0 ? "field required!" : "");
SendButton.Bind(NameTextBox, i => SendButton.Enabled = !(i.Length == 0));
}
扩展
public static class Extention
{
public static void Bind(this Control owner, Control dataSource)
{
List<EventInfo> fields = dataSource.GetType().GetEvents().ToList();
int index = fields.FindIndex(item => item.Name == "TextChanged");
if (index >= 0)
{
Control sender = dataSource as Control;
owner.Text = dataSource.Text;
dataSource.TextChanged += delegate (Object o, EventArgs e) { owner.Text = sender.Text; };
}
}
public static void Bind(this Control owner, Control dataSource, Func<string,string> onChange)
{
List<EventInfo> fields = dataSource.GetType().GetEvents().ToList();
int index = fields.FindIndex(item => item.Name == "TextChanged");
if (index >= 0)
{
Control sender = dataSource as Control;
owner.Text = onChange(sender.Text);
dataSource.TextChanged += delegate (Object o, EventArgs e) { owner.Text = onChange(sender.Text); };
}
}
public static void Bind(this Control owner, Control dataSource, Action<string> onChange)
{
List<EventInfo> fields = dataSource.GetType().GetEvents().ToList();
int index = fields.FindIndex(item => item.Name == "TextChanged");
if (index >= 0)
{
Control sender = dataSource as Control;
onChange(sender.Text);
dataSource.TextChanged += delegate (Object o, EventArgs e) { onChange(sender.Text); };
}
}
}
公共静态类扩展
{
公共静态void绑定(此控件所有者,控件数据源)
{
列表字段=dataSource.GetType().GetEvents().ToList();
int index=fields.FindIndex(item=>item.Name==“TextChanged”);
如果(索引>=0)
{
控件发送方=作为控件的数据源;
owner.Text=dataSource.Text;
dataSource.TextChanged+=delegate(对象o,事件参数e){owner.Text=sender.Text;};
}
}
公共静态void绑定(此控件所有者、控件数据源、Func onChange)
{
列表字段=dataSource.GetType().GetEvents().ToList();
int index=fields.FindIndex(item=>item.Name==“TextChanged”);
如果(索引>=0)
{
控件发送方=作为控件的数据源;
owner.Text=onChange(sender.Text);
dataSource.TextChanged+=委托(对象o,事件参数e){owner.Text=onChange(sender.Text);};
}
}
公共静态void绑定(此控件所有者、控件数据源、操作onChange)
{
列表字段=dataSource.GetType().GetEvents().ToList();
int index=fields.FindIndex(item=>item.Name==“TextChanged”);
如果(索引>=0)
{
控件发送方=作为控件的数据源;
onChange(sender.Text);
dataSource.TextChanged+=委托(对象o,事件参数e){onChange(sender.Text);};
}
}
}
你应该继续写你的标题。标记是不必要的,这意味着C 35;
和数据绑定可以删除,留下“有没有简单的方法?”的答案通常是“是的,有”。标题应该简单地解释你的问题是什么。完成了,希望现在更好!你有没有读过关于这次活动的报道?我想你可以用这个。你试过使用WPF吗?数据绑定在WPF中更为自定义。我不认为有任何神奇的“自动”方式可以做到这一点。是的,我知道事件;有没有办法自己实现propertychanged事件?回溯是:定期通过RS232轮询传感器数据。如果一个传感器的值发生变化,我想在标签或文本框中显示。现在,backroundthreaded计时器需要调用和填充来访问GUI线程;虽然使用数据绑定会更容易,但似乎并非如此:P(将在实际问题中添加回溯以使问题更清楚)@coloss因此,这并不总是一种简单的方法。绑定是一个非常强大的功能,它使您的应用程序更易于管理、更好地由测试驱动并独立于开发人员。我保证你的答案是问题的解决方案,但假设在实际项目中它是不可接受的。@voo谢谢你的评论。我同意你的看法。这是一个简单的解决方案,但在某些情况下肯定不是最好的办法。这真的取决于整个背景,哪条路更好。在我看来,调用解决方案相当不错。我在与WinForms协作的线程中使用它取得了很好的经验。别忘了检查新值是否与旧值不同是的,这也应该有效,因为我认为使用INotifyPropertyChanged更好,因为它是一个标准,当其他开发人员看到它实现时,他理解,类支持绑定逻辑。
public static class Extention
{
public static void Bind(this Control owner, Control dataSource)
{
List<EventInfo> fields = dataSource.GetType().GetEvents().ToList();
int index = fields.FindIndex(item => item.Name == "TextChanged");
if (index >= 0)
{
Control sender = dataSource as Control;
owner.Text = dataSource.Text;
dataSource.TextChanged += delegate (Object o, EventArgs e) { owner.Text = sender.Text; };
}
}
public static void Bind(this Control owner, Control dataSource, Func<string,string> onChange)
{
List<EventInfo> fields = dataSource.GetType().GetEvents().ToList();
int index = fields.FindIndex(item => item.Name == "TextChanged");
if (index >= 0)
{
Control sender = dataSource as Control;
owner.Text = onChange(sender.Text);
dataSource.TextChanged += delegate (Object o, EventArgs e) { owner.Text = onChange(sender.Text); };
}
}
public static void Bind(this Control owner, Control dataSource, Action<string> onChange)
{
List<EventInfo> fields = dataSource.GetType().GetEvents().ToList();
int index = fields.FindIndex(item => item.Name == "TextChanged");
if (index >= 0)
{
Control sender = dataSource as Control;
onChange(sender.Text);
dataSource.TextChanged += delegate (Object o, EventArgs e) { onChange(sender.Text); };
}
}
}