2012-03-17 92 views
0

我正在创建一个使用多个线程的应用程序,因此我想尽可能少地尝试在我的代码中使用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.... 


    } 

回答

0

OnPropertyChanged(property);应指向值,因为这是您的财产的名称。 这不应该指向类型T。 所以这段代码是不正确的:

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

因为属性应始终"Value"

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

当涉及到数据绑定一个应该更新的对象(没关系CLR属性或DependencyObject的)在同一个线程,作为UI在运行。如果您将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。

+0

我知道如何使用dispacher感谢您的帮助。如果你将一个属性绑定到一个UIcontrol,你将能够在一个单独的线程上更新该属性而不会产生异常。此外,你可以在UIcontrols上验证... – 2012-03-18 08:30:48

相关问题