带有值数据绑定的WPF ProgressBar

时间:2013-01-10 16:10:44

标签: c# wpf data-binding progress-bar

我正在尝试在WPF中对ProgressBar的value属性进行数据绑定。我有一个按钮设置为增加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);
        }
    }
}

3 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分:1)

没有代码(已发布)设置Window(或StackPanel)的DataContext。

要确定原因,请在“输出”窗口中查看“绑定错误”。


另外,

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

这会阻止邮件处理,因此您的应用将在5秒钟内“无响应”。不会进行任何输入处理和屏幕更新。繁忙的循环在事件驱动的GUI中根本不好。

将此代码移至Backgroundworker或使用计时器。

答案 2 :(得分:0)

没有数据绑定的其他解决方案。 您可以声明代理

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