TextBoxコントロールをStringBuilderインスタンスにバインドする方法
-
03-07-2019 - |
質問
基礎となる文字列の変更に反応するいくつかのテキストボックスが欲しい。そのため、文字列のコンテンツを変更すると、これらのテキストボックスもすべてコンテンツを変更します。
今では、不変なのでそのためにString型を使用できません。そこで、StringBuilderを使用しました。ただし、TextBoxオブジェクトのTextプロパティはStringのみを取ります。
「バインド」する簡単な方法はありますかStringBuilderオブジェクトをTextBoxのTextプロパティに追加しますか?
どうもありがとう!
PS:TextBoxは現在WPFです。しかし、MonoのためにWindowsフォームに切り替えるかもしれません。
解決
ゲッターがStringbuilderのToString()を返すプロパティを常に公開できます。フォームはこのプロパティにバインドできます。
private StringBuilder _myStringBuilder;
public string MyText
{
get { return _myStringBuilder.ToString(); }
}
他のヒント
多くの人が私が言っていた点を誤解していたため、私の以前の答えはあまりうまく表現されていなかったようですので、人々のコメントを考慮してもう一度試します。
文字列オブジェクトが不変であるからといって、文字列型の変数を変更できないわけではありません。オブジェクトにString型のプロパティがある場合、そのプロパティに新しいStringオブジェクトを割り当てると、プロパティが変更されます(元の回答では、これを変数変更と呼びました。一部の人々は、用語&quotの使用に同意しないようです。 ;このコンテキストでは変更します)。
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プロパティは変更されています(または、必要に応じて変更されています)。
ここで、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メソッドを公開できます。
テキストボックスを継承し、Textプロパティをオーバーライドして、文字列ビルダーを取得して書き込むことができます。
簡単に言えば、いいえ。テキストプロパティは文字列のみを取ります。したがって、ソースが何であれ、それを文字列に変換する必要があります。
多くのテキストボックスに一度だけ簡単に設定できるようにするために、すべてのテキストボックスの値を常に設定するクラスプロパティを設定できます...
public string MyString
{
get
{
///...
}
set
{
textbox1.Text = value;
textbox2.Text = value;
//...
}
}
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(); }
}
}
TextBoxのTextプロパティを文字列プロパティにバインドできます... Stringオブジェクトは不変ですが、String型の変数は完全に可変です...
string mutable = "I can be changed";
mutable = "see?";
ただし、INotifyPropertyChangedを実装するオブジェクトでラップする必要があります。