Как привязать элемент управления TextBox к экземпляру StringBuilder?
-
03-07-2019 - |
Вопрос
Я бы хотел, чтобы несколько текстовых полей реагировали на изменения базовой строки. Поэтому, если бы я изменил содержимое строки, все эти текстовые поля также изменили бы их содержимое.
Теперь я не могу использовать для этого тип String, так как он неизменный. Итак, я пошел с StringBuilder. Но свойство Text объекта TextBox принимает только строку.
Есть ли простой способ "связать"? объект StringBuilder для свойства Text объекта TextBox?
Большое спасибо!
PS: TextBox в настоящее время является WPF. Но я могу перейти на Windows Forms из-за Mono.
Решение
Вы всегда можете предоставить свойство, которое getter возвращает ToString () Stringbuilder. Затем форма может быть связана с этим свойством.
private StringBuilder _myStringBuilder;
public string MyText
{
get { return _myStringBuilder.ToString(); }
}
Другие советы
Похоже, мой предыдущий ответ был сформулирован не очень хорошо, так как многие люди не поняли суть моего высказывания, поэтому я попытаюсь еще раз учесть комментарии людей.
Тот факт, что объект 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 не мутировал, но свойство мутировало (или изменилось, если хотите).
Вот что я использую для привязки StringBuilder к TextBox в 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
}
В ViewModel:
public BindableStringBuilder ErrorMessages { get; set; }
ErrorMessages.AppendLine("Missing Image: " + imagePath);
В Xaml:
<TextBox Text="{Binding ErrorMessages.Text, Mode=OneWay}"/>
Конечно, вы можете использовать другие методы StringBuilder, если вам нужно.
Вы можете унаследовать текстовое поле и переопределить свойство Text для извлечения и записи в построитель строк.
Проще говоря, нет. Свойство Text принимает только строку. Таким образом, независимо от источника, вам придется преобразовать его в строку.
Чтобы можно было легко установить его один раз для многих текстовых полей, у вас может быть свойство класса, которое всегда устанавливает все значения текстового поля ...
public string MyString
{
get
{
///...
}
set
{
textbox1.Text = value;
textbox2.Text = value;
//...
}
}
Я бы обернул 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(); }
}
}
Вы можете привязать свойство Text TextBox к строковому свойству ... Объект String является неизменным, но переменная типа String является полностью изменяемой ...
string mutable = "I can be changed";
mutable = "see?";
Однако вам нужно будет обернуть его в объект, который реализует INotifyPropertyChanged.