繁体   English   中英

Winforms中的两种方式DataBinding

[英]Two Ways DataBinding in Winforms

我正在学习数据绑定,我有一个带有一个属性的类,然后我有另一个带有组合框和2个值“1和2”的类,我创建了一个带有属性的类的数组对象,所以当组合框有1我的文本框会给它一个类[0] .property的值,相反,如果我有2这个发生在类[1] .property这里是代码,所以你会更好地理解:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsFormsApplication1
{
    struct Class1
    {
        public string pollo { get; set; }
    }
}

我的第二堂课:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        Class1[] prova = new Class1[2];
        int a;

        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            a = Convert.ToInt32(comboBox1.SelectedItem) - 1;
            prova[a].pollo = textBox1.Text;
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            a = Convert.ToInt32(comboBox1.SelectedItem) - 1;
            textBox1.DataBindings.Add("Text", prova[a], "pollo", false, DataSourceUpdateMode.OnPropertyChanged);
            textBox1.DataBindings.Clear();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.SelectedIndex = 0;
        }
    }
}

一切正常,但这是一种单向数据绑定实际上我必须使用单击按钮设置属性,在这种情况下,没有这样的区别:

textBox1.DataBindings.Add("Text", prova[a], "pollo", false, DataSourceUpdateMode.OnPropertyChanged);

textBox1 = prova[a];

那么为什么要使用数据绑定? 我的意思是我怎么能用两种方式来自动设置我的属性?

谢谢

您的代码中存在一些问题,导致绑定无法正常工作,从而模糊了实用性。

首先,要明确:正在设置的绑定位于当前选定的Class1对象和TextBoxText属性之间。 您正在使用ComboBox更改当前选定的对象以将TextBox绑定到。 我假设你已经意识到这一点,但我想确定一下。

现在,就代码中的问题而言......

  1. 最严重的问题是您的数据类型Class1被声明为struct而不是class struct类型是值类型 ,意味着只要代码需要对象引用,就会将值的副本装箱 (存储在object的实例中)。 理解这个盒装值是一个副本是非常重要的。 它与您存储在数组中的值完全断开,因此即使成功设置了绑定,对象的更改也不会反映在从数组中检索对象值的代码中的其他位置。

  2. 几乎同样严重的是你在设置后立即清除绑定 这完全否定了数据绑定的要点,即允许框架根据另一个对象的更改自动更新属性值。 所以是的,在你的代码示例中,set-binding-then-clear-binding操作与简单地直接设置属性之间几乎没有任何区别

这两个问题中的任何一个都足以阻止数据绑定以有用的方式工作。 但还有第三个问题......

  1. 您的Class1类型未实现属性更改事件。 在Winforms中,您可以实现名为polloChanged的事件(即属性名称,后跟单词Changed ,拼写和大写完全相同),或者实现INotifyPropertyChanged接口。 如果没有这些机制,双向数据绑定就无法工作,因为框架无法知道属性值何时发生了变化。 (讽刺的是,什么工作目标到源绑定...这是,因为TextBox类实现了TextChanged事件,数据绑定能够设置源属性当目标属性更改,但它不走另一种方法)。

下面是一个代码版本,它充分利用数据绑定,正确实现Class1 (作为实际class ,并使用必要的polloChanged事件),正确配置绑定,并将对象的pollo属性绑定到Label以便它清楚对象的pollo属性正在更新:

class Class1
{
    private string _pollo = "";
    public string pollo
    {
        get { return _pollo; }
        set
        {
            _pollo = value;
            Raise(polloChanged, this);
        }
    }

    private static void Raise(EventHandler handler, object sender)
    {
        if (handler != null)
        {
            handler(sender, EventArgs.Empty);
        }
    }

    public event EventHandler polloChanged;
}


public partial class Form1 : Form
{
    private Class1[] _prova =
    {
        new Class1 { pollo = "<not set 1>" },
        new Class1 { pollo = "<not set 2>" }
    };

    public Form1()
    {
        InitializeComponent();

        comboBox1.SelectedIndex = 0;
    }

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
    {
        // Obviously in a more complicated data binding scenario, you might
        // want to be more specific about which binding(s) is(are) being
        // removed, rather than just clearing everything.
        textBox1.DataBindings.Clear();
        label1.DataBindings.Clear();

        // If the user edits the text in the TextBox, the pollo property
        // of the currently-selected object will be immediately updated
        textBox1.DataBindings.Add("Text", _prova[comboBox1.SelectedIndex],
            "pollo", false, DataSourceUpdateMode.OnPropertyChanged);

        // We're never going to change the label1.Text property directly,
        // so the binding doesn't ever need to update the source property.
        label1.DataBindings.Add("Text", _prova[comboBox1.SelectedIndex],
            "pollo", false, DataSourceUpdateMode.Never);
    }
}

我假设您可以在表单中推断出必要的textBox1comboBox1label1控件,而不是让我发布所有Designer代码。


最后,如果你更喜欢INotifyPropertyChanged方法,这就是你的Class1使用这种技术的样子:

class Class1 : INotifyPropertyChanged
{
    private string _pollo = "";
    public string pollo
    {
        get { return _pollo; }
        set
        {
            _pollo = value;
            OnPropertyChanged();
        }
    }

    private void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;

        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM