【问题标题】:Binding property to control in WinformsWinforms中控制的绑定属性
【发布时间】:2011-08-18 12:05:46
【问题描述】:

将属性绑定到控件的最佳方法是什么,以便在更改属性值时,控件的绑定属性也会随之更改。

如果我有一个属性FirstName,我想将它绑定到文本框的txtFirstName 文本值。因此,如果我将 FirstName 更改为值“Stack”,那么属性 txtFirstName.Text 也会更改为值“Stack”。

我知道这听起来可能是个愚蠢的问题,但我会很感激你的帮助。

【问题讨论】:

    标签: c# vb.net winforms binding


    【解决方案1】:

    你必须实现INotifyPropertyChanged并添加绑定到文本框。

    我将提供 C# 代码 sn-p。希望对你有帮助

    class Sample : INotifyPropertyChanged
    {
        private string firstName;
        public string FirstName
        {
            get { return firstName; }
            set
            {
                firstName = value;
                InvokePropertyChanged(new PropertyChangedEventArgs("FirstName"));
            }
        }
    
        #region Implementation of INotifyPropertyChanged
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        public void InvokePropertyChanged(PropertyChangedEventArgs e)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, e);
        }
    
        #endregion
    }
    

    用法:

     Sample sourceObject = new Sample();
     textbox.DataBindings.Add("Text",sourceObject,"FirstName");
     sourceObject.FirstName = "Stack"; 
    

    【讨论】:

    • 这将在textBox.Text 更改时更新sourceObject。您还需要订阅PropertyChanged 事件以在sourceObject.FirstName 更改时更新文本框内容(这是原始问题)。
    • @David - 这有两种工作方式。刚刚创建应用并对其进行了测试
    • @Stecya 这并不完全正确。鉴于上面的示例,当我更改 sourceObject.FirstName 时它将起作用,并且当我更改 UI 中文本框中的文本并离开文本框时它将起作用。但是,当我通过执行textbox.Text = "Anything" 在代码隐藏中更新文本框的文本时,它不会更新sourceObject 中的属性。所以我认为绑定更新是由 .NET 在任何控件的内部离开事件上触发的,不是吗?请纠正我,当我错了。对我来说,这种情况还不够。
    • 要将控件中的更改绑定到属性,请使用 textbox.DataBindings.Add("Text",sourceObject,"FirstName", false, DataSourceUpdateMode.OnPropertyChanged);
    • 很好。尽管为了您的方便,我建议使用自动获取属性名称的方法:` protected void OnPropertyChanged() { if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(new System.Diagnostics.StackFrame(1).GetMethod().Name .Replace("set_", ""))); }`
    【解决方案2】:

    已接受答案的简化版本,它不需要您在每个属性设置器中手动键入属性名称,例如 OnPropertyChanged("some-property-name")。相反,您只需调用 OnPropertyChanged() 而不使用参数:

    您至少需要 .NET 4.5。 CallerMemberName 在 System.Runtime.CompilerServices 命名空间中

    public class Sample : INotifyPropertyChanged
    {
        private string _propString;
        private int _propInt;
    
    
        //======================================
        // Actual implementation
        //======================================
        public event PropertyChangedEventHandler PropertyChanged;
    
        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
        //======================================
        // END: actual implementation
        //======================================
    
    
        public string PropString
        {
            get { return _propString; }
            set
            {
                // do not trigger change event if values are the same
                if (Equals(value, _propString)) return;
                _propString = value;
    
                //===================
                // Usage in the Source
                //===================
                OnPropertyChanged();
    
            }
        }
    
        public int PropInt
        {
            get { return _propInt; }
            set
            {
                // do not allow negative numbers, but always trigger a change event
                _propInt = value < 0 ? 0 : value;
                OnPropertyChanged();
            }
        }
    }
    

    用法保持不变:

    var source = new Sample();
    textbox.DataBindings.Add("Text", source, "PropString");
    source.PropString = "Some new string";
    

    希望这对某人有所帮助。

    【讨论】:

    • 我在“CallerMemberName”上遇到错误。它必须在某个地方定义吗?
    • 您至少需要 .NET 4.5。 CallerMemberName 在 System.Runtime.CompilerServices 命名空间中
    • [NotifyPropertyChangedInvocator] 即使在使用 .net 4.6.1 和 System.Runtime.CompilerServices 命名空间时也不存在。
    猜你喜欢
    • 2011-10-20
    • 2011-10-08
    • 1970-01-01
    • 1970-01-01
    • 2011-07-02
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多