如何将 TextBox 控件绑定到 StringBuilder 实例?

发布于 2024-07-11 10:02:47 字数 297 浏览 6 评论 0原文

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

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

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

非常感谢!

PS:文本框目前是WPF。 但由于 Mono,我可能会转向 Windows 窗体。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

冷︶言冷语的世界 2024-07-18 10:02:47

您始终可以公开一个属性,该属性的 getter 返回 Stringbuilder 的 ToString()。 然后表单可以绑定到该属性。

private StringBuilder _myStringBuilder;

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

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(); }
}
听你说爱我 2024-07-18 10:02:47

下面是我在 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


}

在 ViewModel 中:

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

在 Xaml 中:

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

当然,如果需要,您可以公开其他 StringBuilder 方法。

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.

待"谢繁草 2024-07-18 10:02:47

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

仅仅因为 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 属性已经发生了变化(如果您愿意,也可以更改)。

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

神仙妹妹 2024-07-18 10:02:47

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

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

丑丑阿 2024-07-18 10:02:47

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

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

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

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;
    //...
  }
}
晒暮凉 2024-07-18 10:02:47

我将使用 Add 方法、Text 方法和 OnChanged 事件将 StringBuilder 包装在自定义类中。

连接 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(); }
   }
}

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 event fires, use the Text method to do a ToString on the StringBuilder.

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(); }
   }
}
野却迷人 2024-07-18 10:02:47

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

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文