Как связать элемент управления TextBox с экземпляром StringBuilder? - PullRequest
9 голосов
/ 05 января 2009

Я бы хотел, чтобы несколько текстовых полей реагировали на изменения базовой строки. Поэтому, если бы я изменил содержимое строки, все эти текстовые поля также изменили бы их содержимое.

Теперь я не могу использовать тип String для этого, поскольку он неизменен. Итак, я пошел с StringBuilder. Но свойство Text объекта TextBox принимает только строку.

Есть ли простой способ "привязать" объект StringBuilder к свойству Text TextBox?

Большое спасибо!

PS: TextBox в настоящее время WPF. Но я мог бы перейти на Windows Forms из-за Mono.

Ответы [ 7 ]

9 голосов
/ 06 января 2009

Похоже, мой предыдущий ответ был сформулирован не очень хорошо, так как многие люди не поняли суть моего высказывания, поэтому я попробую еще раз, принимая во внимание комментарии людей.

Тот факт, что объект 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 имеет мутированное (или измененное, если вы предпочитаете).

7 голосов
/ 09 сентября 2015

Вот что я использую для привязки 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, если вам нужно.

7 голосов
/ 05 января 2009

Вы всегда можете предоставить свойство, которое getter возвращает ToString () Stringbuilder. Затем форма может быть привязана к этому свойству.

private StringBuilder _myStringBuilder;

public string MyText
{
  get { return _myStringBuilder.ToString(); }
}
1 голос
/ 05 января 2009

Проще говоря, нет. Свойство Text принимает только строку. Таким образом, независимо от источника, вам придется преобразовать его в строку.

Чтобы вы могли легко установить его один раз для многих текстовых полей, у вас может быть свойство класса, которое всегда устанавливает все значения текстового поля ...

public string MyString
{
  get
  {
   ///... 
  }
  set 
  {
    textbox1.Text = value;
    textbox2.Text = value;
    //...
  }
}
1 голос
/ 05 января 2009

Вы можете унаследовать текстовое поле и переопределить свойство Text для извлечения и записи в построитель строк.

0 голосов
/ 06 января 2009

Я бы обернул 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(); }
   }
}
0 голосов
/ 05 января 2009

Вы можете привязать свойство Text TextBox к строковому свойству ... Объект String является неизменным, но переменная типа String является полностью изменяемой ...

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

Однако вам нужно будет обернуть его в объект, который реализует INotifyPropertyChanged.

...