可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I read some about DataBinding, mostly complicated things like SQL or whatever XAML and stuff.
All I want my programm to do is, if the "value" of a variable changes just write it in a textbox or label. (using WindowsForms)
So far what I have:
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 just has a public property name. On startup lable1 will show my "Hello" string. Then on button click the name property will change. On debug I saw the actual DataSource of "bs" contains the new property value, but the label will not show anything...
Is there any realtivly easy way to do this?
The Backround is: periodically there will be a polling of sensor data throug RS232. If the value of one sensor changes I want to show this in label or textbox. Now a backroundthreaded timer will need invokes and stuff to access the GUI thread; thought this would be easier with databinding but seems not :P
Thanks to all, great site, great work! :)
回答1:
Another way to make things work without implementing 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);
}
}
}
The trick is to have event with the name combined by name of property and Changed
suffix and to raise it whenever value of your property is changed
回答2:
In order your code would work you should implement INotifyPropertyChanged interface in your binded class. Without it your binding simply doesn't know, when the change occures. There you should implenent the logic, according to which you would notify your subscribers about which when something changed in your class (the setter part) and what has changed (PropertyChangedEventArgs). See example for your class:
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"));
}
}
}
And change the property name from "name" to "Name" in your binding:
label1.DataBindings.Add(new Binding("Text", bs, "Name", false, DataSourceUpdateMode.OnPropertyChanged));
回答3:
// 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;
}
}
}
回答4:
I created an extension method for this that I would like to share
Usage
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));
}
Extension
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); };
}
}
}
回答5:
I'm not sure if that is what you want but you can can write whatever you variable contains into the Textbox or Label by using the control.Text property.
textBox1.Text ="Some other Text"
or
string variable = "Hello 2";
textBox1.Text = variable;
Why dou you want to use Databinding? Its mutch easier this way.