【问题标题】:Bind control to property not working将控件绑定到属性不起作用
【发布时间】:2012-04-03 00:41:39
【问题描述】:

我正在创建一个使用多个线程的应用程序,因此我想尝试在我的代码中尽可能少地使用 UIControls。我这样做的方法是将控件绑定到我的代码中的属性,这样我就可以通过更改该属性来更新控件,如果该属性在不同的线程上更新并不重要。无论如何,我正在创建以下代码,以便该类创建我的绑定。

public static class MyExtensionMethods 
{

    public static TextBoxBind<T> BindTextBox<T>(this TextBox textbox, string property=null)
    {
        return new TextBoxBind<T>(textbox,property);
    }
}



public class TextBoxBind<T> : INotifyPropertyChanged
{
    string property;

    protected T _Value;
    public T Value
    {
        get { return _Value; }
        set { _Value = value; OnPropertyChanged(property); }
    }

    public event PropertyChangedEventHandler PropertyChanged = delegate { };
    protected void OnPropertyChanged(string propertyName){
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    public TextBoxBind(TextBox textbox, string property)
    {
        if (property == null)
        {
            property = "Value";
        }
        this.property = property;

        Binding b = new Binding(property)
       {
            Source = this
       };

        b.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
        textbox.SetBinding(TextBox.TextProperty, b);
    }
}

在我的 XAML 上我有:

 <TextBox  Name="textBox2"  />

因此,我将能够使用我发布的第一个代码:

        var newTextBox2 = textBox2.BindTextBox<int>();
        newTextBox2.Value = 50; // this will update the textBox2.Text = "2"
        // also every time I update the value of textBox2  newTextBox2.Value will update as well

问题是当我尝试将其绑定到自定义对象时。以这段代码为例:

    public class Person 
    {
        public string Name { get; set; }
        public string Age { get; set; }

        public override string ToString()
        {
            return Age.ToString();
        }            

    }

    void LogIn_Loaded(object sender, RoutedEventArgs e)
    {
        txtUsuario.Focus();

        var newTextBox2 = textBox2.BindTextBox<Person>("Age");

        // here newTextBox2 never updates....


    }

【问题讨论】:

    标签: c# wpf binding textbox


    【解决方案1】:

    OnPropertyChanged(property); 应该指向 Value,因为那是您的属性的名称。 这不应该指向T 类型。 所以这段代码是不对的:

    if (property == null) 
    { 
      property = "Value"; 
    }
    

    因为属性应始终为"Value"

    public T Value     
    {     
        get { return _Value; }     
        set { _Value = value; OnPropertyChanged("Value"); }     
    }  
    

    【讨论】:

      【解决方案2】:

      当涉及到数据绑定时,应该从运行 UI 的同一线程更新对象(不管 CLR 属性或 DependencyObject)。如果你有一个 UI 元素绑定到代码中的某些东西,从一个单独的线程更新它会导致异常。但是,您始终可以检索您的 UI 线程并在那里执行属性更新。 这是一段代码,我在与您类似的情况下使用它:

      ThreadStart updateLogs = delegate()
      {
          ObservableCollection<LogMessage> newLogs = this._parcer.Parce();
          foreach (LogMessage log in newLogs)
              LogMessages.Add(log);
      };
      App.Current.Dispatcher.BeginInvoke(updateLogs, null);
      

      此代码块在与运行一个 UI 的线程不同的线程中运行。所以我提取代码,实际上将绑定源(即 LogMessages)更新为委托 updateLogs,然后在 UI 线程中运行此委托,并将其传递给应用程序调度程序。

      尽管如此,WPF 应用程序可以有多个 Dispather,例如,如果您在单独的线程中创建单独的窗口,尽管这种方法很少见。但以防万一,DependencyObject 类有一个 Dispatcher 属性,它引用了拥有该对象的 Dispather。

      【讨论】:

      • 我知道如何使用调度程序感谢您的帮助。如果将属性绑定到 UIcontrol,您将能够在单独的线程上更新该属性而不会出现异常。此外,您可以在 UIcontrols 上获得验证...
      猜你喜欢
      • 1970-01-01
      • 2016-04-23
      • 1970-01-01
      • 1970-01-01
      • 2017-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多