带有值绑定的WPF ProgressBar

本文关键字:WPF ProgressBar 绑定 | 更新日期: 2023-09-27 17:51:18

我试图在WPF中绑定ProgressBar的值属性。我设置了一个按钮来增加ProgressBar的值的边界属性。当我按下按钮时,它应该使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);
        }
    }
}

带有值绑定的WPF ProgressBar

线程。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);
}

还有其他不需要数据绑定的解决方案。你可以声明一个委托

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

并在按钮

的click事件中使用它
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);
        }

没有代码(张贴)设置窗口(或StackPanel)的DataContext。

要确定原因,请查看Output窗口中的绑定错误。


此外,

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

这将阻止消息处理,因此您的应用程序将"无响应"5秒。不会进行任何输入处理和屏幕更新。在事件驱动的GUI中,繁忙循环并不好。