Howto bind TextBox control to a StringBuilder instance?

18,352

Solution 1

You could always expose a property that's getter returns the ToString() of the Stringbuilder. The form could then bind to this property.

private StringBuilder _myStringBuilder;

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

Solution 2

Here what I use to bind StringBuilder to TextBox in 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


}

In ViewModel:

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

In Xaml:

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

Of course you can expose other StringBuilder methods if you need.

Solution 3

It seems my previous answer wasn't worded very well, as many people misunderstood the point I was making, so I will try again taking into account people's comments.

Just because a String object is immutable does not mean that a variable of type String cannot be changed. If an object has a property of type String, then assigning a new String object to that property causes the property to change (in my original answer, I referred to this as the variable mutating, apparently some people do not agree with using the term "mutate" in this context).

The WPF databinding system can bind to this property. If it is notified that the property changes through INotifyPropertyChanged, then it will update the target of the binding, thus allowing many textboxes to bind to the same property and all change on an update of the property without requiring any additional code.

Therefore, there is no need to use StringBuilder as the backing store for the property. Instead, you can use a standard String property and implement 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 can bind to this and will automatically pick up and changes made in the value of the property. No, the String object has not mutated, but the String property has mutated (or changed, if you prefer).

Solution 4

You could inherit the text box and override the Text property to retrieve and write to the string builder.

Solution 5

Simply put, no. Text property only takes a String. So whatever the source, you'll have to convert it to a String.

To enable you to easily set it once for many textboxes, you can have a class property that always sets all textbox values...

public string MyString
{
  get
  {
   ///... 
  }
  set 
  {
    textbox1.Text = value;
    textbox2.Text = value;
    //...
  }
}
Share:
18,352
user51710
Author by

user51710

Updated on October 19, 2022

Comments

  • user51710
    user51710 over 1 year

    I would like several textboxes to react to changes of an underlying string. So if I were to change the content of the string, all those textboxes would change their content too.

    Now, I can't use the String type for that as it is immutable. So I went with StringBuilder. But the Text property of a TextBox object only takes String.

    Is there an easy way to "bind" the StringBuilder object to the Text property of a TextBox?

    Many thanks!

    PS: The TextBox is currently WPF. But I might switch to Windows Forms because of Mono.