views:

2631

answers:

6

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.

A: 

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

Tom Anderson
I would still have to issue and handle notifications in case of a change to the underlying StringBuilder, wouldn't I?
+1  A: 

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(); }
}
Ray Booysen
Thanks for the answers Ray.But I would still have to manually assign MyText to textbox.Text, wouldn't I?What I am looking for is a construct in which all participants share the same memory location.
If you're using WPF, the TextBox would look like this<TextBox Text="{Binding Path=MyText}" /> and the binding would take care of this for you.,
Ray Booysen
If the textboxes are bound to the property via the above syntax, WPF will handle all the binding for you. As long as you cater for any changes to the StringBuilder by calling NotifyPropertyChanged("MyText) in the case of INotifyPropertyChanged, all would be well.
Ray Booysen
With those hints I should be able to create the binding. Thany you.I was looking/hoping for a way to do it without event handling but just now realized that that is not possible, because at some point the textbox has to be notified that it needs to repaint.
By the way. Looking at your description: What if I wanted to bind and unbind datasources to and from controls and even add new controls with a respective binding at runtime.I was looking for textBox1.DataBinding.Add(...) but IntelliSense did not know that. Any idea?
Have a look at this link over here for bindings in code:http://msdn.microsoft.com/en-us/library/ms771500.aspxHope this helps. :)
Ray Booysen
That helped very much. Thanky you!
I marked this answer as the accepted answer as the comments were very helpful.
A: 

You can bind the Text property of a TextBox to a string property... The String object is immutable, but a variable of type String is perfectly mutable...

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

You would need to wrap it up in an object that implements INotifyPropertyChanged, however.

Giraffe
A string object is not mutable. When modifying a string like you've just done, what really occurs is a new string is created.
Ray Booysen
@Ray: I was just about to say that :)
CMS
+1 for Ray. String is most definitely immutable. Every String/string assignment allocates new space in memory.
Kon
string being immutable doesn't stop you binding to a property of an object that is of type string. This would be the usual way to do this.
Sam Meldrum
@Sam, Giraffe didn't address binding at all. He's incorrectly talking about string mutability (is that a word?).
Kon
@fallen888 - yes he did. The first sentence reads: "You can bind..."
Sam Meldrum
I stand corrected. :)
Kon
Still.. the rest of the answer is bad (no offense), IMHO.
Kon
-1 @Giraffe, you should read again for mutability and string-objects - you just got something wrong.
BeowulfOF
Not sure about that. The essence of the right answer for binding with wpf is there. If he'd said that a Property of type String can be changed and it is the property you need to bind to (rather than going on about mutability of variables, which is really variability, he would've got a good answer.
Sam Meldrum
Has there been an edit I can't see or something? Giraffe explicitly states that the String object is immutable. I'm not sure it's a really *good* answer, but I don't think it deserves the stick it's getting.
Jon Skeet
@Jon - I agree. No edit you can't see.
Sam Meldrum
Err, not sure where I said a string object was mutable... in fact, I think I explicitly stated it wasn't wit the phrase "The String object is immutable".I edited to add the last line about implementing INotifyPropertyChanged to allow the binding system to know the variable has changed.
Giraffe
Also, I go by the definition that if the *value of a variable* changes, you can say that the variable has mutated. If that's good enough for Eric Lippert, it's good enough for me: http://blogs.msdn.com/ericlippert/archive/2007/12/13/immutability-in-c-part-five-lolz.aspx
Giraffe
A: 

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;
    //...
  }
}
Kon
I think the posted was looking for a way to bind data and not have a concrete list of textboxes to update. :)
Ray Booysen
@Ray, I know what you mean, but he's looking for a way to update multiple controls at once... and this is one way.
Kon
A: 

I would wrap the StringBuilder in a custom class with an Add method, Text method, and an OnChanged event.

Wire up the Add method such that when it is called it adds the text to the StringBuilder instance and fires the event. Then when the even fires, use the Text method to do a ToString on the StringBuilder.

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

Chris Brandsma
+3  A: 

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).

Giraffe
A good complete answer +1
Sam Meldrum