7

WPF で ProgressBar の値プロパティをデータバインドしようとしています。ProgressBar の値のデータバインドされた int プロパティをインクリメントするようにボタンを設定しました。ボタンを押すと、ProgressBar の値が 1 から 100 までカウントアップされるはずです。これが私のXAMLです...

<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);
        }
    }
}
4

3 に答える 3

7

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

以下を使用して、UI スレッドをブロックせずに実行を一時停止できます。Thread.Sleep(50)通話を次のように置き換えますWait(50)

/// <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);
}
于 2013-01-10T16:24:43.960 に答える
1

データバインディングのない他のソリューションがあります。デリゲートを宣言できます

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);
        }
于 2013-01-10T16:34:35.313 に答える
1

Window (または StackPanel) の DataContext を設定するコード (投稿) はありません。

原因を確認するには、[出力] ウィンドウでバインディング エラーを確認します。


さらに、

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

これによりメッセージ処理がブロックされるため、アプリは 5 秒間「無応答」になります。入力処理や画面更新は行われません。ビジー ループは、イベント ドリブンの GUI では適切ではありません。

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

于 2013-01-10T16:15:40.670 に答える