【问题标题】:Problem with DataBindings, explain please数据绑定问题,请解释
【发布时间】:2010-10-28 18:15:55
【问题描述】:
public partial class Form1 : Form
{
    MyClass myClass = new MyClass("one", "two");

    public Form1()
    {
        InitializeComponent();
        textBox1.DataBindings.Add("Text", myClass, "Text1", false, DataSourceUpdateMode.Never);
        textBox2.DataBindings.Add("Text", myClass, "Text2", false, DataSourceUpdateMode.Never);
    }

    private void saveButton_Click(object sender, EventArgs e)
    {
        myClass.Text1 = textBox1.Text;
        myClass.Text2 = textBox2.Text;
        //textBox1.DataBindings["Text"].WriteValue();
        //textBox2.DataBindings["Text"].WriteValue();
    }
}

public class MyClass : INotifyPropertyChanged
{
    private string _Text1;
    private string _Text2;

    public event PropertyChangedEventHandler PropertyChanged;

    public string Text1
    {
        get { return _Text1; }
        set { _Text1 = value; OnPropertyChanged(new PropertyChangedEventArgs("Text1")); }
    }

    public string Text2
    {
        get { return _Text2; }
        set { _Text2 = value; OnPropertyChanged(new PropertyChangedEventArgs("Text2")); }
    }

    public MyClass(string text1, string text2)
    {
        Text1 = text1;
        Text2 = text2;
    }

    protected void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (PropertyChanged != null) PropertyChanged(this, e);
    }
}

我认为我想要达到的目标非常清楚。我希望我的表单将我的两个TextBoxes 中所做的更改保存到myClass。但是,每当我在编辑两个文本框后按下保存按钮并调用saveButton_Click 时,第二个textBox2Text 就会返回原始文本(“两个”)。我尝试使用BindingWriteValue 函数,但同样的事情发生了。使用 .net 4.0。

编辑感谢您的回答,但我不需要解决方法。我可以自己找到它们。我只需要更好地了解绑定是如何工作的。我想了解为什么会这样?

【问题讨论】:

    标签: c# .net winforms data-binding


    【解决方案1】:

    显然,更新数据源上的任何值都会导致所有绑定都被更新。这解释了行为(设置myClass.Text1 导致textBox2 更新为myClass.Text2 的当前值)。不幸的是,我能找到的几篇帖子几乎都只是说,“这就是它的工作原理”。

    处理此问题的一种方法是创建一个BindingSource,设置BindingSource.DataSource = myClass,然后将您的TextBoxes 绑定到BindingSource

    BindingSource 引发 ListChanged 事件,如果基础数据源是一个列表并且项目被添加、删除等,如果DataSource 属性发生变化。您可以通过将BindingSource.RaiseListChangedEvents 设置为false 来抑制这些事件,这样您就可以在myClass 上设置多个属性,而无需数据绑定更新绑定的控件。

    public partial class Form1 : Form
    {
        MyClass myClass = new MyClass("one", "two");
        BindingSource bindingSource = new BindingSource();
    
        public Form1()
        {
            InitializeComponent();
    
            bindingSource.DataSource = myClass;
    
            textBox1.DataBindings.Add("Text", bindingSource, "Text1", true, DataSourceUpdateMode.Never);
            textBox2.DataBindings.Add("Text", bindingSource, "Text2", true, DataSourceUpdateMode.Never);                
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
            bindingSource.RaiseListChangedEvents = false;
            myClass.Text1 = textBox1.Text;
            myClass.Text2 = textBox2.Text;
            bindingSource.RaiseListChangedEvents = true;
        }
    }
    

    HTH

    【讨论】:

    • 那行得通。但我不明白为什么如果我的属性不在列表中。
    • @jsoldi,我编辑了我的答案,包括当DataSource 属性更改时也会引发ListChanged
    【解决方案2】:

    您需要改变进行数据绑定的方式。试试这个。

    MyClass myClass = new MyClass("one", "two");
    
    public Form1()
    {
        InitializeComponent();
        textBox1.DataBindings.Add("Text", myClass, "Text1", false, DataSourceUpdateMode.OnPropertyChanged);
        textBox2.DataBindings.Add("Text", myClass, "Text2", false, DataSourceUpdateMode.OnPropertyChanged);
    }
    
    private void saveButton_Click(object sender, EventArgs e)
    {
        // your object should already have new text values entered.
        // Save your object!
    
        //myClass.Text1 = textBox1.Text;
        //myClass.Text2 = textBox2.Text;
        //textBox1.DataBindings["Text"].WriteValue();
        //textBox2.DataBindings["Text"].WriteValue();
    }
    

    关键是DataSourceUpdateMode,这将允许文本框的文本属性在属性更改时级联到您的自定义对象中。我希望这会有所帮助。

    [编辑]

    我相信您需要做的是实现您的要求: TextBox1.DataBindings[0].ControlUpdateMode = ControlUpdateMode.Never 这个link 应该提供一些额外的信息。

    【讨论】:

    • 但是我不想在TextBoxText改变时保存数据,我希望它在按下保存按钮时改变。我怎样才能做到这一点? DataSourceUpdateMode.NeverWriteValue() 不就是为了实现这种功能吗?
    • 不要使用数据绑定。只需手动将表单构造函数中的文本值分配给文本框,如下所示:textBox1.Text = myClass.Text1;
    • @jsoldi - 然后不要对这些值使用数据绑定 - 在 saveButton_Click 事件中设置值。这就是数据绑定的用途——它将控件实例的属性绑定到数据对象的属性。
    • 我试过了。但我希望如果我必须在窗口中编辑相同的 MyClass 对象并且一个保存更改,另一个自动更新。我可以找到一种解决方法,例如将textBox2.Text 保存在一个临时字符串中,然后将其分配给saveButton_Click,但我的问题是为什么会发生这种情况? 应该会这样吗?
    • 是的,这就是数据绑定开箱即用的方式。看看我上次的编辑,这应该可以实现你所追求的。
    猜你喜欢
    • 2010-12-23
    • 2013-07-27
    • 1970-01-01
    • 2011-01-17
    • 2017-02-16
    • 2011-10-18
    相关资源
    最近更新 更多