8

我想要几个文本框来响应底层字符串的变化。因此,如果我要更改字符串的内容,所有这些文本框也会更改其内容。

现在,我不能使用 String 类型,因为它是不可变的。所以我选择了 StringBuilder。但是 TextBox 对象的 Text 属性只接受 String。

有没有一种简单的方法可以将 StringBuilder 对象“绑定”到 TextBox 的 Text 属性?

非常感谢!

PS:TextBox 目前是 WPF。但是我可能会因为 Mono 而切换到 Windows 窗体。

4

7 回答 7

11

您总是可以公开一个 getter 返回 Stringbuilder 的 ToString() 的属性。然后表单可以绑定到这个属性。

private StringBuilder _myStringBuilder;

public string MyText
{
  get { return _myStringBuilder.ToString(); }
}
于 2009-01-05T16:33:03.883 回答
10

这是我用来在 WPF 中将 StringBuilder 绑定到 TextBox 的内容:

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 方法。

于 2015-09-09T16:37:16.400 回答
9

看来我之前的回答措辞不是很好,因为很多人误解了我的观点,所以我会考虑人们的评论再次尝试。

仅仅因为 String 对象是不可变的,并不意味着 String 类型的变量不能更改。如果一个对象具有 String 类型的属性,那么为该属性分配一个新的 String 对象会导致该属性发生变化(在我原来的答案中,我将此称为变量变异,显然有些人不同意使用术语“变异”在这种情况下)。

WPF 数据绑定系统可以绑定到此属性。如果通过 INotifyPropertyChanged 通知属性更改,那么它将更新绑定的目标,从而允许许多文本框绑定到同一个属性,并在属性更新时全部更改,而无需任何额外的代码。

因此,不需要使用 StringBuilder 作为属性的后备存储。相反,您可以使用标准字符串属性并实现 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 属性发生了变异(或更改,如果您愿意)。

于 2009-01-06T10:12:45.553 回答
1

您可以继承文本框并覆盖 Text 属性以检索和写入字符串生成器。

于 2009-01-05T16:32:10.453 回答
1

简单地说,没有。Text 属性只接受一个字符串。因此,无论来源如何,您都必须将其转换为字符串。

为了使您能够轻松地为许多文本框设置一次,您可以拥有一个始终设置所有文本框值的类属性...

public string MyString
{
  get
  {
   ///... 
  }
  set 
  {
    textbox1.Text = value;
    textbox2.Text = value;
    //...
  }
}
于 2009-01-05T16:34:36.423 回答
0

我会用方法、方法和事件将其包装StringBuilder在自定义类中。AddTextOnChanged

连接该Add方法,以便在调用它时将文本添加到StringBuilder实例并触发事件。然后当事件触发时,使用该Text方法ToStringStringBuilder.

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(); }
   }
}
于 2009-01-05T22:21:37.597 回答
-5

您可以将 TextBox 的 Text 属性绑定到字符串属性... String 对象是不可变的,但 String 类型的变量是完全可变的...

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

但是,您需要将其包装在实现 INotifyPropertyChanged 的​​对象中。

于 2009-01-05T16:33:39.843 回答