【问题标题】:C# - Binding TextBox to an integerC# - 将文本框绑定到整数
【发布时间】:2010-12-02 14:53:22
【问题描述】:

如何将文本框绑定到整数?例如,将单元绑定到 textBox1。

public partial class Form1 : Form
{
    int unit;

    public Form1()
    {
        InitializeComponent();


    }

    private void Form1_Load(object sender, EventArgs e)
    {
        textBox1.DataBindings.Add("Text", unit, "???");
    }

【问题讨论】:

  • 它派生自Form类。

标签: c# winforms data-binding


【解决方案1】:

我喜欢做的一件事是为表单创建“表示”层。正是在这一层中,我声明了绑定到窗体上的控件的属性。在这种情况下,控件是一个文本框。

在这个例子中,我有一个带有文本框的表单来显示 IP 地址

我们现在通过文本框属性创建绑定源。选择数据绑定-> 文本。单击向下箭头;选择“添加项目数据源”。

这将启动数据源向导。选择对象。点击“下一步”。

现在选择具有将绑定到文本框的属性的类。在本例中,我选择了 PNetworkOptions。选择完成以结束向导。不会创建 BindingSource。

下一步是从绑定的类中选择实际的属性。从 DataBindings->Text 中,选择向下箭头并选择将绑定到文本框的属性名称。

在具有您的属性的类中,INotifyPropertyChanged 必须为 IP 地址字段的 2 路通信实现

public class PNetworkOptions : IBaseInterface, INotifyPropertyChanged
{
    private string _IPAddress;


    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }

    public string IPAddress
    {
        get { return _IPAddress; }
        set
        {
            if (value != null && value != _IPAddress)
            {
                _IPAddress = value;
                NotifyPropertyChanged("IPAddress");
            }
        }
    }
}

在表单构造函数中,我们要专门定义绑定

Binding IPAddressbinding = mskTxtIPAddress.DataBindings.Add("Text", _NetOptions, "IPAddress",true,DataSourceUpdateMode.OnPropertyChanged);

【讨论】:

    【解决方案2】:

    您可以使用绑定源(见评论)。最简单的改变是:

    public partial class Form1 : Form
    {
        public int Unit { get; set; }
        BindingSource form1BindingSource;
    
        private void Form1_Load (...)
        {
            form1BindingSource.DataSource = this;
            textBox1.DataBindings.Add ("Text", form1BindingSource, "Unit");
        }
    }
    

    但是,如果您将数据分开一点,您将获得一些概念上的清晰性:

    public partial class Form1 : Form
    {
        class MyData {
            public int Unit { get; set; }
        }
    
        MyData form1Data;
        BindingSource form1BindingSource;
    
        private void Form1_Load (...)
        {
            form1BindingSource.DataSource = form1Data;
            textBox1.DataBindings.Add ("Text", form1BindingSource, "Unit");
        }
    }
    

    HTH。注意省略了访问修饰符。

    【讨论】:

    • Marc Gravell 的更改更简单,看起来还不错。我习惯于按照一般原则将所有内容绑定到 BindingSource 对象;它就在那里,它是为此目的而构建的,不妨使用它。
    • BindingSource 纯粹作为一个抽象层;您可以直接绑定到实例和列表。
    • 我不知道你所说的 purely 是什么抽象层次; BindingSource 中有实际的代码可以做一些事情,比如管理货币。
    • 货币由货币管理器管理,绑定IList/IListSource时默认获得该管理器;您只需通过BindingSource 获得更多 控制权。所以如果你需要它,太好了! BindingSource 还提供了用于控制为列表创建新项目的点,但您可以通过许多其他方式来做到这一点,包括简单地实现正确的 ComponentModel 接口。
    • 确实如此。您可以获得更多控制权,BindingSource 实现起来很便宜,它是标准框架的一部分,并且正是为此目的而构建的。我同意:您没有必须使用 BindingSource,但出于上述原因,我倾向于使用它,除非有令人信服的理由不使用它。
    【解决方案3】:

    它必须是实例的公共属性;在这种情况下,“this”就足够了:

    public int Unit {get;set;}
    private void Form1_Load(object sender, EventArgs e)
    {
        textBox1.DataBindings.Add("Text", this, "Unit");
    }
    

    对于双向通知,您需要UnitChangedINotifyPropertyChanged

    private int unit;
    public event EventHandler UnitChanged; // or via the "Events" list
    public int Unit {
        get {return unit;}
        set {
            if(value!=unit) {
                unit = value;
                EventHandler handler = UnitChanged;
                if(handler!=null) handler(this,EventArgs.Empty);
            }
        }
    }
    

    如果您不希望在公共 API 上使用它,可以将其包装在某个隐藏类型中:

    class UnitWrapper {
        public int Unit {get;set;}
    }
    private UnitWrapper unit = new UnitWrapper();
    private void Form1_Load(object sender, EventArgs e)
    {
        textBox1.DataBindings.Add("Text", unit, "Unit");
    }
    

    有关信息,“事件列表”的内容类似于:

        private static readonly object UnitChangedKey = new object();
        public event EventHandler UnitChanged
        {
            add {Events.AddHandler(UnitChangedKey, value);}
            remove {Events.AddHandler(UnitChangedKey, value);}
        }
        ...
        EventHandler handler = (EventHandler)Events[UnitChangedKey];
        if (handler != null) handler(this, EventArgs.Empty);
    

    【讨论】:

    • Marc,当您将事件命名为 xxxChanged 为属性 xxx 然后它在幕后处理时,我找不到有关该技巧的更多信息。你可以发布一个链接或者至少是如何调用这个技巧吗?谢谢
    • 这是 PropertyDescriptor 实现的一部分——基本上它寻找 *Changed 事件的模式。但是,您通常也可以使用 INotifyPropertyChanged
    • 属性命名技巧,当xxxAttribute类可以使用时,就像xxx在msdn中写得很好。但这种行为真的很隐蔽。我试图用谷歌搜索更多关于它的信息,但失败了(可能是因为“改变”这个词困扰了搜索查询):) 无论如何,再次感谢
    • @pkuderov 属性是编译器行为—— *Changed 在运行时应用。其他的包括诸如 ShouldSerialize 之类的东西 - 这也是由 PropertyDescriptor 应用的
    猜你喜欢
    • 1970-01-01
    • 2010-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 2017-04-07
    • 2018-11-16
    相关资源
    最近更新 更多