Как привязать элемент управления TextBox к экземпляру StringBuilder?

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

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

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

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

PS: TextBox в настоящее время является WPF. Но я могу переключиться на Windows Forms из-за Mono.

PS: TextBox в настоящее время является WPF. Но я могу переключиться на Windows Forms из-за Mono.

user51710 05.01.2009 19:39
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
8
1
17 456
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

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

Мне все равно придется выпускать и обрабатывать уведомления в случае изменения базового StringBuilder, не так ли?

user51710 05.01.2009 19:59
Ответ принят как подходящий

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

private StringBuilder _myStringBuilder;

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

Спасибо за ответы, Рэй. Но мне все равно придется вручную назначать MyText для textbox.Text, не так ли? Я ищу конструкцию, в которой все участники используют одну и ту же ячейку памяти.

user51710 05.01.2009 19:45

Если вы используете WPF, TextBox будет выглядеть так: <TextBox Text = "{Binding Path = MyText}" />, и привязка позаботится об этом за вас.,

Ray Booysen 05.01.2009 19:47

Если текстовые поля привязаны к свойству с помощью указанного выше синтаксиса, WPF выполнит всю привязку за вас. Пока вы вносите любые изменения в StringBuilder, вызывая NotifyPropertyChanged ("MyText) в случае INotifyPropertyChanged, все будет хорошо.

Ray Booysen 05.01.2009 19:48

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

user51710 05.01.2009 20:04

Кстати. Глядя на ваше описание: что, если бы я хотел привязать и отвязать источники данных от элементов управления и даже добавить новые элементы управления с соответствующей привязкой во время выполнения. Я искал textBox1.DataBinding.Add (...), но IntelliSense этого не знал. Любая идея?

user51710 05.01.2009 20:08

Взгляните на эту ссылку здесь для привязок в коде: msdn.microsoft.com/en-us/library/ms771500.aspx Надеюсь, это поможет. :)

Ray Booysen 05.01.2009 20:56

Это очень помогло. Спасибо!

user51710 07.01.2009 12:32

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

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

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

Строковый объект не может быть изменен. При изменении строки, как вы только что сделали, на самом деле происходит создание новой строки.

Ray Booysen 05.01.2009 19:36

@Ray: Я как раз собирался это сказать :)

Christian C. Salvadó 05.01.2009 19:37

+1 для Рэя. Строка определенно неизменна. Каждое присвоение String / String выделяет новое пространство в памяти.

Kon 05.01.2009 19:40

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

Sam Meldrum 05.01.2009 19:43

@Sam, Giraffe вообще не связывал адреса. Он неправильно говорит о изменчивости строк (это слово?).

Kon 05.01.2009 19:45

@ fallen888 - да, он это сделал. Первое предложение гласит: «Вы можете связать ...»

Sam Meldrum 05.01.2009 19:48

Все-таки .. в остальном ответ плохой (без обид) ИМХО.

Kon 05.01.2009 19:51

-1 @Giraffe, вы должны прочитать еще раз, чтобы узнать о изменчивости и строковых объектах - вы просто ошиблись.

Oliver Friedrich 05.01.2009 19:56

Не уверен в этом. Суть правильного ответа на привязку с wpf есть. Если бы он сказал, что свойство типа String можно изменить, и это свойство нужно привязать (вместо того, чтобы говорить об изменчивости переменных, что на самом деле является изменчивостью, он бы получил хороший ответ.

Sam Meldrum 05.01.2009 19:57

Я не вижу правки, или что-то в этом роде? Giraffe явно заявляет, что объект String неизменяем. Я не уверен, что это действительно ответ хорошо, но я не думаю, что он заслуживает той палки, которую получает.

Jon Skeet 05.01.2009 20:11

Эээ, не уверен, где я сказал, что строковый объект был изменяемым ... на самом деле, я думаю, что я явно заявил, что это не было с фразой «Объект String неизменяем». Я отредактировал, чтобы добавить последнюю строку о реализации INotifyPropertyChanged, чтобы позволить системе привязки знать, что переменная изменилась.

Giraffe 06.01.2009 11:27

Кроме того, я исхожу из определения, что если значение переменной изменяется, вы можете сказать, что переменная изменилась. Если этого достаточно для Эрика Липперта, этого достаточно для меня: blogs.msdn.com/ericlippert/archive/2007/12/13/…

Giraffe 06.01.2009 11:31

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

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

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

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

Ray Booysen 05.01.2009 19:37

@Ray, я понимаю, что вы имеете в виду, но он ищет способ обновить сразу несколько элементов управления ... и это один из способов.

Kon 05.01.2009 19:42

Я бы обернул 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(); }
   }
}

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

Тот факт, что объект 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 имеет изменилось (или изменилось, если хотите).

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

Это полезно. Обратите внимание, что BindableStringBuilder должен быть инициализирован: public BindableStringBuilder ErrorMessages { get ; } = new BindableStringBuilder();

blearyeye 07.09.2018 18:15

Другие вопросы по теме