我想要几个文本框来对底层字符串的更改做出反应。因此,如果我要更改字符串的内容,那么所有这些文本框也会更改其内容。
现在,我不能使用String类型,因为它是不可变的。所以我选择了StringBuilder。但是TextBox对象的Text属性只接受String。
是否有一种简单的方法将StringBuilder对象“绑定”到TextBox的Text属性?
非常感谢!
PS:TextBox目前是WPF。但由于Mono,我可能会转而使用Windows Forms。
答案 0 :(得分:9)
我的上一个答案似乎没有措辞得当,因为很多人误解了我的观点,所以我会再次考虑人们的评论。
仅仅因为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 :(得分:7)
你总是可以公开一个getter返回Stringbuilder的ToString()的属性。然后表单可以绑定到此属性。
private StringBuilder _myStringBuilder;
public string MyText
{
get { return _myStringBuilder.ToString(); }
}
答案 2 :(得分:7)
这里我用来将StringBuilder绑定到WPF中的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方法。
答案 3 :(得分:1)
您可以继承文本框并覆盖Text属性以检索并写入字符串构建器。
答案 4 :(得分:1)
简单地说,不。 Text属性只接受一个String。因此,无论来源如何,您都必须将其转换为String。
为了让您能够轻松地为许多文本框设置一次,您可以拥有一个始终设置所有文本框值的类属性...
public string MyString
{
get
{
///...
}
set
{
textbox1.Text = value;
textbox2.Text = value;
//...
}
}
答案 5 :(得分:0)
我会使用StringBuilder
方法,Add
方法和Text
事件将OnChanged
打包到自定义类中。
连接Add
方法,以便在调用它时将文本添加到StringBuilder
实例并触发事件。然后,当事件触发时,使用Text
方法在ToString
上执行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(); }
}
}
答案 6 :(得分:-5)
您可以将TextBox的Text属性绑定到字符串属性... String对象是不可变的,但String类型的变量是完全可变的......
string mutable = "I can be changed";
mutable = "see?";
但是,您需要将其包装在实现INotifyPropertyChanged的对象中。