C# 带值数据绑定的 WPF ProgressBar
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14262220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF ProgressBar with Value databinding
提问by user1451495
I'm trying to databind the value property of a ProgressBar in WPF. I have a button set up to increment the databound int property for the Value of the ProgressBar. When I push the button it should make the ProgressBar's Value count up from 1 to 100. However... it doesn't seem to be working and I am not sure what I am doing wrong. Here is my XAML...
我正在尝试对 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>
and here is my code behind...
这是我背后的代码......
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);
}
}
}
回答by Henk Holterman
There is no code (posted) that sets the DataContext of the Window (or StackPanel).
没有设置窗口(或 StackPanel)的 DataContext 的代码(已发布)。
To be sure about the cause, watch the Output window for Binding errors.
要确定原因,请查看输出窗口中的绑定错误。
And in addition,
此外,
private void goButton_Click(object sender, RoutedEventArgs e)
{
for (Percent = 0; Percent <= 100; Percent++)
{
Thread.Sleep(50);
}
}
This blocks message processing so your app will be 'unresponsive' for 5 seconds. No input processing and no screen updates will take place. A busy loop is simply not good in an event-driven GUI.
这会阻止消息处理,因此您的应用将在 5 秒内“无响应”。不会进行输入处理和屏幕更新。繁忙的循环在事件驱动的 GUI 中是不好的。
Move this code to a Backgroundworker or use a Timer.
将此代码移动到后台工作程序或使用计时器。
回答by bic
The Thread.Sleep is blocking the UI thread and stopping the animation of the progress bar.
Thread.Sleep 正在阻塞 UI 线程并停止进度条的动画。
You can use the following to pause execution without blocking the UI thread. Replace your Thread.Sleep(50)
call with Wait(50)
您可以使用以下命令在不阻塞 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);
}
回答by Santux
There are other solutions without the databinding. You can declare a delegate
还有其他没有数据绑定的解决方案。你可以声明一个委托
private delegate void UpdateProgressBarDelegate(System.Windows.DependencyProperty dp, Object value);
private delegate void UpdateProgressBarDelegate(System.Windows.DependencyProperty dp, Object value);
and use it in the click event of the button
并在按钮的点击事件中使用
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);
}