2009-01-05 45 views
9

我想要幾個文本框對底層字符串的變化作出反應。所以如果我要改變字符串的內容,所有這些文本框也會改變它們的內容。如何將TextBox控件綁定到StringBuilder實例?

現在,我不能使用字符串類型,因爲它是不可變的。所以我用StringBuilder去了。但是TextBox對象的Text屬性只能使用String。

有沒有簡單的方法來將StringBuilder對象綁定到TextBox的Text屬性?

非常感謝!

PS:TextBox目前是WPF。但是由於Mono,我可能會切換到Windows窗體。

+0

Winforms或WPF? – 2009-01-05 16:31:33

+0

PS:TextBox目前是WPF。但是由於Mono,我可能會切換到Windows窗體。 – user51710 2009-01-05 16:39:19

回答

7

你總是可以暴露一個getter的屬性返回Stringbuilder的ToString()。該表單可以綁定到這個屬性。

private StringBuilder _myStringBuilder; 

public string MyText 
{ 
    get { return _myStringBuilder.ToString(); } 
} 
+0

感謝您的解答。 但我仍然必須手動分配MyText到textbox.Text,不是嗎? 我在找的是一個構造,所有參與者共享相同的內存位置。 – user51710 2009-01-05 16:45:04

+1

如果您使用的是WPF,則TextBox看起來像這樣 並且綁定將爲您處理此問題。, – 2009-01-05 16:47:52

+0

如果文本框綁定到屬性通過上面的語法,WPF將爲你處理所有的綁定。只要你在INotifyPropertyChanged的情況下通過調用NotifyPropertyChanged(「MyText)來滿足對StringBuilder的任何修改,一切都會好起來的。 – 2009-01-05 16:48:45

1

您可以繼承文本框並覆蓋Text屬性以檢索並寫入字符串構建器。

+0

如果對底層StringBuilder進行更改,我仍然需要發出和處理通知,對嗎? – user51710 2009-01-05 16:59:24

-5

您可以將文本框的Text屬性綁定到一個字符串屬性... String對象是不可變的,但是String類型的變量是完全可變...

string mutable = "I can be changed"; 
mutable = "see?"; 

你會但是需要將它包裝在實現INotifyPropertyChanged的對象中。

0

簡而言之,沒有。 Text屬性只接受一個String。因此無論來源如何,您都必須將其轉換爲字符串。

爲了讓您能夠輕鬆設置一次,許多文本框,你可以有一個類屬性總是設置所有文本框的值...

public string MyString 
{ 
    get 
    { 
    ///... 
    } 
    set 
    { 
    textbox1.Text = value; 
    textbox2.Text = value; 
    //... 
    } 
} 
0

我會繼續Add包裹StringBuilder在自定義類方法,Text方法和OnChanged事件。

連線Add方法,使得當它被調用時,它將文本添加到StringBuilder實例並觸發事件。然後當事件觸發時,使用Text方法在StringBuilder上執行ToString

public class StringBuilderWrapper 
{ 
    private StringBuilder _builder = new StringBuilder(); 
    private EventHandler<EventArgs> TextChanged; 
    public void Add(string text) 
    { 
    _builder.Append(text); 
    if (TextChanged != null) 
     TextChanged(this, null); 
    } 
    public string Text 
    { 
    get { return _builder.ToString(); } 
    } 
} 
8

看來我以前的答案是沒有的措詞非常好,因爲很多人誤解了我提出的觀點,所以我會再次嘗試考慮到人的評論。

僅僅因爲一個String對象是不可變的並不意味着一個String類型的變量不能被改變。如果一個對象有一個String類型的屬性,那麼將一個新的String對象賦值給該屬性會導致該屬性發生變化(在我最初的回答中,我將此稱爲變量變異,顯然有些人不同意使用術語「變異「)。

WPF數據綁定系統可以綁定到此屬性。如果通過INotifyPropertyChanged通知該屬性更改,則它將更新綁定的目標,從而允許許多文本框綁定到相同的屬性,並且在更新屬性時全部更改,而不需要任何其他代碼。

因此,不需要使用StringBuilder作爲屬性的後備存儲。相反,您可以使用標準的String屬性並實現INotifyPropertyChanged。

public class MyClass : INotifyPropertyChanged 
{ 
    private string myString; 

    public string MyString 
    { 
     get 
     { return myString; } 
     set 
     { 
      myString = value; 
      OnPropertyChanged("MyString"); 
     } 
    } 

    protected void OnPropertyChanged(string propertyName) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
     { handler(this, new PropertyChangedEventArgs(propertyName)); } 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    #endregion 
} 

WPF可以綁定到這一點,並會自動拾取在財產的值進行變化。不,String對象沒有發生變異,但String屬性發生了變異(如果您願意,也可以更改)。

1

這裏我使用StringBuilder的綁定到文本框在WPF:

public class BindableStringBuilder : INotifyPropertyChanged 
{ 
    private readonly StringBuilder _builder = new StringBuilder(); 

    private EventHandler<EventArgs> TextChanged; 

    public string Text 
    { 
     get { return _builder.ToString(); } 
    } 

    public int Count 
    { 
     get { return _builder.Length; } 
    } 

    public void Append(string text) 
    { 
     _builder.Append(text); 
     if (TextChanged != null) 
      TextChanged(this, null); 
     RaisePropertyChanged(() => Text); 
    } 

    public void AppendLine(string text) 
    { 
     _builder.AppendLine(text); 
     if (TextChanged != null) 
      TextChanged(this, null); 
     RaisePropertyChanged(() => Text); 
    } 

    public void Clear() 
    { 
     _builder.Clear(); 
     if (TextChanged != null) 
      TextChanged(this, null); 
     RaisePropertyChanged(() => Text); 
    } 

    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void RaisePropertyChanged(string property) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(property)); 
     } 
    } 

    public void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression) 
    { 
     if (propertyExpression == null) 
     { 
      return; 
     } 

     var handler = PropertyChanged; 

     if (handler != null) 
     { 
      var body = propertyExpression.Body as MemberExpression; 
      if (body != null) 
       handler(this, new PropertyChangedEventArgs(body.Member.Name)); 
     } 
    } 

    #endregion 


} 

在視圖模型:

public BindableStringBuilder ErrorMessages { get; set; } 
ErrorMessages.AppendLine("Missing Image: " + imagePath); 

在XAML:

<TextBox Text="{Binding ErrorMessages.Text, Mode=OneWay}"/> 

當然可以公開其他的StringBuilder方法,如果你需要。