我正在使用Windows Vista和Visual Studio 2010.创建.Net 4 Windows窗体应用程序。删除默认表单上的进度条,添加代码以处理表单加载事件并在那里执行progressBar1.Value = 100;
。
开始调试,你会看到动画在大约半秒内将进度条移动到100。
我的项目中需要2个进度条。一个用于“全局进展”,第二个用于“当前步进”,因此第二个从0到100,并且回到0以进行下一步。问题是,进度条对于某些快速步骤来说速度很慢,它永远不会达到100而且看起来很奇怪。
有没有办法摆脱那个动画?在WPF中没关系,但我宁愿继续使用Windows Forms。
答案 0 :(得分:15)
这就是Vista / 7进度条的设计方式。当您更改进度条的值时,该栏会逐渐动画化为该值。
我知道避免此问题的唯一方法是在更新进度条时倒退,如下所示:
progressBar1.Value = n;
if (n>0)
progressBar1.Value = n-1;
有关更完整的讨论,请参阅Disabling .NET progressbar animation when changing value?
答案 1 :(得分:13)
在相关问题中使用进度条和Heffernan's tip向前推进Reinhart's extension method approach时,我想出了自己的解决方案。
该解决方案非常无缝,并成功处理了值Maximum
时您将遇到的问题。这种ProgressBar
的扩展方法可以缓解在Windows Vista上运行时 WinForms ProgressBar
控件中出现的渐进式动画样式导致的延迟 7(我还没有在Windows 8上测试过。)
public static class ExtensionMethods
{
/// <summary>
/// Sets the progress bar value, without using 'Windows Aero' animation.
/// This is to work around a known WinForms issue where the progress bar
/// is slow to update.
/// </summary>
public static void SetProgressNoAnimation(this ProgressBar pb, int value)
{
// To get around the progressive animation, we need to move the
// progress bar backwards.
if (value == pb.Maximum)
{
// Special case as value can't be set greater than Maximum.
pb.Maximum = value + 1; // Temporarily Increase Maximum
pb.Value = value + 1; // Move past
pb.Maximum = value; // Reset maximum
}
else
{
pb.Value = value + 1; // Move past
}
pb.Value = value; // Move to correct value
}
}
样本使用:
private void backgroundWorker_ProgressChanged(object sender,
ProgressChangedEventArgs e)
{
progressBar.SetProgressNoAnimation(e.ProgressPercentage);
}
答案 2 :(得分:2)
您可以轻松编写自定义进度条以显示其值而无需动画。以下是一个简单的实现,用于显示从0到100的进度并恢复为0.
public class ProgressBarDirectRender : UserControl
{
private int _value;
public int Value
{
get { return _value; }
set
{
if (value < 0 || value > 100)
throw new ArgumentOutOfRangeException("value");
_value = value;
const int margin = 1;
using (var g = CreateGraphics())
{
if (_value == 0)
ProgressBarRenderer.DrawHorizontalBar(g, ClientRectangle);
else
{
var rectangle = new Rectangle(ClientRectangle.X + margin,
ClientRectangle.Y + margin,
ClientRectangle.Width * _value / 100 - margin * 2,
ClientRectangle.Height - margin * 2);
ProgressBarRenderer.DrawHorizontalChunks(g, rectangle);
}
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
ProgressBarRenderer.DrawHorizontalBar(e.Graphics, ClientRectangle);
}
}
答案 3 :(得分:0)
我喜欢Derek W's answer,并且设法找到了一种支持数据绑定的解决方案。我从System.Windows.Forms.ProgressBar
继承并创建了新的可绑定属性。否则相同:
[DefaultBindingProperty("ValueNoAnimation")]
public class NoAnimationProgressBar : ProgressBar
{
/// <summary>
/// Sets the progress bar value, without using 'Windows Aero' animation.
/// This is to work around (hack) for a known WinForms issue where the progress bar
/// is slow to update.
/// </summary>
public int ValueNoAnimation
{
get => Value;
set
{
// To get around the progressive animation, we need to move the
// progress bar backwards.
if (value != Maximum)
Value = value + 1; // Move past
else
{
// Special case as value can't be set greater than Maximum.
Maximum = value + 1;
Value = value + 1;
Maximum = value;
}
Value = value; // Move to correct value
}
}
}
您可以像这样绑定到属性(viewModel具有一个名为Value
的int属性):
var dataSource = new BindingSource { DataSource = _viewModel };
progressBarBindingHack.DataBindings.Add("ValueNoAnimation", dataSource, "Value");
答案 4 :(得分:0)
要做一个更简单的答案,如here所示:
pbar.Value = value;
pbar.Value = value - 1;
pbar.Value = value;
说明:
它会在PB增大时对其进行动画处理,但在其减小时不会进行动画处理。这就是为什么上述黑客会“解决”问题的原因。