2013-01-10 24 views
5

私はWPFでProgressBarのvalueプロパティをデータバインドしようとしています。 ProgressBarのValueのdatabound intプロパティをインクリメントするように設定されたボタンがあります。私がボタンを押すと、ProgressBarの値が1から100までカウントアップされるはずです。しかし、それは動作していないように見えますし、何が間違っているのか分かりません。ここに私のXAMLは、ウィンドウのDataContextの設定を一切コード(投稿)がありません...ここWPF ProgressBar with valueデータバインディング

<Window x:Class="ProgressBarExample2.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="250" Width="400" Background="WhiteSmoke"> 
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"> 
    <Button Name="goButton" Height="30" Width="50" Margin="0,10,0,50" Click="goButton_Click">GO!</Button> 
    <ProgressBar Name="progressBar" Width="300" Height="30" Value="{Binding Percent, UpdateSourceTrigger=PropertyChanged}" /> 
</StackPanel> 

とは、私のコードが背後にある...

public partial class MainWindow : Window, INotifyPropertyChanged 
{ 
    #region INotifyPropertyChanged 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected void NotifyPropertyChange(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    #endregion 

    private int percent = 0; 
    public int Percent 
    { 
     get { return this.percent; } 
     set 
     { 
      this.percent = value; 
      NotifyPropertyChange("Percent"); 
     } 
    } 

    public MainWindow() 
    { 
     InitializeComponent(); 
    } 


    private void goButton_Click(object sender, RoutedEventArgs e) 
    { 
     for (Percent = 0; Percent <= 100; Percent++) 
     { 
      Thread.Sleep(50); 
     } 
    } 
} 
+0

のクリックイベントで使用を宣言することができ、あなたはおそらく、タイマーを開始クリックボタンのtimer-を追加してみてくださいすることができます。タイマーコールバックインクリメントでは、適切なデータバインディングを使用してPercent-を実行するだけで済みます。タイマーのコールバックはバックグラウンドスレッドにあるので、メインスレッドはプログレスバーを自由に更新することができます – Sarang

答えて

1

である(またはStackPanel)。

原因を確認するには、出力ウィンドウでバインディングエラーを確認してください。


しかも、

private void goButton_Click(object sender, RoutedEventArgs e) 
{ 
    for (Percent = 0; Percent <= 100; Percent++) 
    { 
     Thread.Sleep(50); 
    } 
} 

このブロックのメッセージ処理のアプリは、5秒間 '無反応' になりますので。入力処理や画面の更新は行われません。ビジーなループは、イベント駆動型のGUIではうまくいかない。

このコードをバックグラウンドワーカーに移動するか、タイマーを使用してください。

+0

Ahh thats忘れてしまったこと... okそれは一種の修正ですが、リアルタイムで値を更新しません...私は睡眠時間を増やしても、0から100%にジャンプします。 – user1451495

+0

それにも答えが追加されました。 –

6

Thread.SleepはUIスレッドをブロックし、進行状況バーのアニメーションを停止しています。

UIスレッドをブロックせずに実行を一時停止するには、以下を使用できます。削除しましたデリゲート

/// <summary> 
/// Stop execution for a specific amount of time without blocking the UI 
/// </summary> 
/// <param name="interval">The time to wait in milliseconds</param> 
public static void Wait(int interval) 
{ 
    ExecuteWait(() => Thread.Sleep(interval)); 
} 

public static void ExecuteWait(Action action) 
{ 
    var waitFrame = new DispatcherFrame(); 

    // Use callback to "pop" dispatcher frame 
    IAsyncResult op = action.BeginInvoke(dummy => waitFrame.Continue = false, null); 

    // this method will block here but window messages are pumped 
    Dispatcher.PushFrame(waitFrame); 

    // this method may throw if the action threw. caller's responsibility to handle. 
    action.EndInvoke(op); 
} 
+0

UIが凍結されていない理由を理解しようと一日も無駄になりました。初心者。 – NotAgain

0

データバインディングのない他のソリューションがあります。Wait(50)

EDITを使用してThread.Sleep(50)コールを交換してください。 あなたがデリゲート

private delegate void UpdateProgressBarDelegate(System.Windows.DependencyProperty dp, Object value);

とボタン

private void goButton_Click(object sender, RoutedEventArgs e) 
     { 
      //Configure the ProgressBar 
      progressBar.Minimum = 0; 
      progressBar.Maximum = 100; 
      progressBar.Value = 0; 

      //Stores the value of the ProgressBar 
      double value = 0; 

      //Create a new instance of our ProgressBar Delegate that points 
      // to the ProgressBar's SetValue method. 
      UpdateProgressBarDelegate updatePbDelegate = new UpdateProgressBarDelegate(progressBar.SetValue); 

      //Tight Loop: Loop until the ProgressBar.Value reaches the max 
      do 
      { 
       value += 1; 

       /*Update the Value of the ProgressBar: 
        1) Pass the "updatePbDelegate" delegate that points to the ProgressBar1.SetValue method 
        2) Set the DispatcherPriority to "Background" 
        3) Pass an Object() Array containing the property to update (ProgressBar.ValueProperty) and the new value */ 
       Dispatcher.Invoke(updatePbDelegate, 
        System.Windows.Threading.DispatcherPriority.Background, 
        new object[] { ProgressBar.ValueProperty, value }); 

      } 
      while (progressBar.Value != progressBar.Maximum); 
     } 
関連する問題