C#数据绑定-自动将更改的属性写入标签或文本框

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

我读了一些关于数据绑定的书,大部分是复杂的东西,比如SQL或任何XAML之类的东西。 我想让我的程序做的就是,如果变量的“值”改变了,就把它写在文本框或标签中。(使用Windows窗体)

到目前为止,我有:

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); };
            }
        }
    }