2016-07-10 15 views
1

このサイトでは同じ質問が何度も尋ねられています。しかし、私は何時間もの苦労してSOの記事を読んでからそれを理解することができなかった特別な問題(たぶん?)を持っています。WPF-ボタンにTextBlockをバインドする

問題は簡単に説明されていますが、私はConnectボタンを含むWPFフォームを持っています。このボタンを押すと、そのフォームにテキストブロックが表示され、 "Connecting ..."という単語が表示されます。ボタンを押すと、いくつかのハンドシェーク操作が関連するC#コードで実行されます。これには時間がかかります。プログラムが接続に失敗した場合、テキストブロックは「Failed!」に変更する必要があります。それ以外の場合は、「成功」に変わります。

は今、この単純な問題のために、私は私のXAMLに書いた:

<Window x:Class="WpfTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="300" Width="200"> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition /> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <Button x:Name="connecting" Content="Connect" FontWeight="Bold" Click="startConnection" 
       Width="60" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="0"/> 
     <TextBlock x:Name="comm_stat" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" 
       Text="{Binding Content}"/> 
    </Grid> 
</Window> 

そして(this answerに触発さ)C#コード:

using System; 
using System.Text; 
using System.Windows; 
using System.ComponentModel; 

namespace WpfTest 
{ 
    public class DynamicObj : INotifyPropertyChanged 
    { 
     public DynamicObj() : this(string.Empty) { } 
     public DynamicObj(string txt) { Content = txt; } 
     private string _name; 
     public string Content 
     { 
      get { return _name; } 
      set { 
       _name = value; 
       OnPropertyChanged("Content"); 
      } 
     } 

     public event PropertyChangedEventHandler PropertyChanged; 
     public void OnPropertyChanged(string PropertyName) 
     { 
      if (PropertyChanged != null) 
       PropertyChanged(this, new PropertyChangedEventArgs(PropertyName)); 
     } 
    } 

    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 
      DataContext = this; 
      comm_stat.DataContext = new DynamicObj(); 
     } 
     private void startConnection(object sender, RoutedEventArgs e) 
     { 
      comm_stat.Text = "Connecting..."; 

      bool connect2device = false; 
      // do the handshaking operations. the result is then assigned to connect2device 

      comm_stat.Text = connect2device ? "Succeed." : "Failed!"; 
      // some other operations 
     } 
    } 
} 

私はボタンをクリックしたときに今の問題は、ありますテキストブロックにテキストは表示されません。プログラムはstartConnectionメソッドが終了するのを待ってから、結合されたテキストブロックを更新するためです。しかし、のボタンを押すと、テキストブロックがの直後に変更されます。これどうやってするの?

+0

UIスレッドで時間のかかる操作を開始するようです。したがって、UIスレッドは処理が完了するのを待っているので、バインディングを更新することはできません。 –

+0

あなたは何を提案しますか?私はC#noob @ qqww2です –

+1

単に 'Task.Run'を使って操作を開始し、それを待ちます。 googleで 'async-await'を検索して、基本を学ぶことができます。 –

答えて

3

次のようなBackgroundWorkerを使用することができます。

bool connect2device = false; 

private void startConnection(object sender, RoutedEventArgs e) 
{ 
    comm_stat.Text = "Connecting..."; 

    // do the handshaking operations. the result is then assigned to connect2device 

    BackgroundWorker worker = new BackgroundWorker(); 
    worker.DoWork += DoWork; 
    worker.RunWorkerCompleted += Completed; 

    worker.RunWorkerAsync(); 
} 

private void Completed(object sender, RunWorkerCompletedEventArgs e) 
{ 
    comm_stat.Text = connect2device ? "Succeed." : "Failed!"; 
} 

private void DoWork(object sender, DoWorkEventArgs e) 
{ 
    //Change with actual work. 
    Thread.Sleep(1000); 
    connect2device = true; 
} 

ワンサイドノートでは、あなたが実際にテキストを変更するバインディングを使用していないということです。 comm_stat.Text = "Connecting...";はテキストプロパティを直接設定し、DynamicObjオブジェクトはまったく使用されません。 MVVMに関するいくつかのチュートリアルを読むことは良いことかもしれません。

関連する問題