2009-01-05 98 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方法,如果你需要。

相关问题