質問

C#で小さなチャットアプリケーションを作成し、コンソールアプリケーションとして開始しました。ただし、WPFを使用してGUIを作成します。これは、 InitializeConnection() SendMessage(string msg)などの関数を持つ DanMessengerClient という名前のクラスです。

すでにVisual StudioでUIを設計しており、デフォルトでWindow1.xaml.csに Window1 クラスを作成しました。 " Send"のイベントハンドラーを作成しました。現在のところ、テキストエリアにダミーテキストのみを追加するボタン。私の質問は、 WINDow1クラスからSendMessage()関数を呼び出す方法

です。

そのクラスでオブジェクトを作成しようとしましたが、最初のクラス内からテキストボックスにアクセスする必要があるため(つまり、メッセージを受信したときにテキストボックスを更新します)、Window1クラスへの参照を追加すると無限ループで参照を作成し続けるため、StackOverflow 例外。

GUIアプリケーションは初めてです。どうすればいいですか?

役に立ちましたか?

解決

WPFでデータを表示する標準的な方法は、コントロールをそれにバインドすることです( MSDNのデータバインディング)。おそらく、メッセンジャークラスをラップまたはリファクタリングして、バインド可能なプロパティを公開する必要があります。たとえば、メッセンジャークラスはMessageTextというプロパティを公開し、メッセージを受信するたびに更新します。

// INotifyPropertyChanged interface implementation and plumbing

public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
  if (PropertyChanged != null)
    PropertyChanged(this, new PropertyChangedEventArgs(propertyName);
}

// The property you are going to bind to

private string _messageText = String.Empty;

public string MessageText
{
  get { return _messageText; }
  set
  {
    _messageText = value;
    OnPropertyChanged("MessageText");
  }
}

// How to modify your code to update the bindable property

private void OnMessageReceive(string message) // assuming this method already exists
{
  MessageText = MessageText + Environment.NewLine + message;
}

TextBox.Textプロパティをこの新しいプロパティにバインドします:

<TextBox Text="{Binding MessageText, Mode=OneWay}" />

これは、メッセンジャーオブジェクトがウィンドウのDataContextとして設定されていることを前提としています。ウィンドウがメッセンジャーを作成するとき:

public class Window1()
{
  _myMessenger =  = new DanMessengerClient();
  this.DataContext = _myMessenger;
}

メッセンジャークラスがこれを機能させるには、INotifyPropertyChangedを実装する必要があることに注意してください。また、ユーザーがTextBoxを編集してもMessageTextプロパティが破壊されないように、OneWayバインディングに注意してください。 (TextBlockを使用して、ユーザーがまったく編集できないようにすることもできます。)

この設定が完了すると、WPFは_myMessenger.MessageTextプロパティの変更を自動的に監視し、発生時にTextBox.Textを更新します(つまり、メッセージの受信時)。

最後に、送信方法について:テキストを渡すだけです:

private void SendButton_Click(...)
{
  _myMessenger.Send(MyTextBox.Text);
}

Name属性を使用して、送信するメッセージを含むテキストボックスに名前を付けます。

<TextBox Name="MyTextBox" />

他のヒント

Itowlsonが言っていることを少し広げてください:

このようなインターフェースを作成することから始めます:

interface IMessagingClient
{
    string MessageToSend { get; set; }
    string MessageBuffer { get; }
    void SendMessage();
}

このインターフェースを実装するクラスの振る舞いは非常に単純でなければなりません。メッセージが受信されると、メッセージは MessageBuffer に追加されます(おそらく前に改行が付きます)。メッセージを送信するには、 MessageToSend を設定して SendMessage()を呼び出します。これにより、送信されたメッセージも MessageBuffer に追加されます。これを単純にするためにスキップしている実装の詳細はたくさんあります。

次に、 IMessagingClient および INotifyPropertyChanged を実装したテストクラスを作成します。このクラスは実際には何もする必要はありません。ほとんどの場合、ランダムな間隔でランダムなテストメッセージを生成し、 MessageBuffer を更新するだけです。また、 SendMessage が呼び出されると、 MessageToSend がクリアされ、 MessageBuffer が更新されます。

ウィンドウにコードを追加してこのクラスのインスタンスを作成し、 DataContext を設定します。発信 TextBox MessageToSend にバインドし、着信 TextBlock MessageBuffer にバインドし、 SendMessage を呼び出すボタン

テストオブジェクトに対してUIを動作させたら、同じインターフェイスを実装する別のクラスを作成します。このクラスのみが、プロパティセッターが相互運用するプライベート DanMessengerClient オブジェクトを作成します。次に、代わりにウィンドウでこのオブジェクトのインスタンスを作成します。

実際のメッセージングクライアントは、おそらくより洗練されたものになる必要があります。たとえば、 LastMessageReceived プロパティを実装して、そのテキストで特別なことを行うことができます。 ToolTip 。そして、 MessageBuffer プロパティは実際には何らかの方法でリッチテキストをサポートする必要があるかもしれません。しかし、これは良い出発点です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top