此WPF ProgressBar奇数渲染行为是否是Bug? [英] Is this WPF ProgressBar Odd render behaviour a Bug?
问题描述
希望有人可以提供帮助. 我有一个简单的场景,在 WPF 中,单击复选框可以驱动进度条.复选框包含在UserControl中,进度栏位于简单的WPF客户端窗口中. 在用户控件上,我正在使用两个依赖项属性: 1)现有的Tag属性具有我希望绑定到进度条值的值,并且 2)称为CbCount的DP,代表复选框的总数.
Hope someone can help. I have a simple scenario where clicking checkboxes is driving a progress bar in WPF. The checkboxes are contained in a UserControl and the Progress bar is in a simple WPF client window. On the user control I am using two dependency properties: 1) the existing Tag property has the value I wish to bind to the progress bar value and 2) a DP called CbCount which represents the total number of checkboxes.
问题: 当应用程序运行时,进度条的进度显示为100%完成,即使通过Snoop我也可以看到该值实际上为0.单击复选框,一切正常.
The problem: When the application runs the progress bar's progress shows as being 100% complete even though via Snoop I can see the value is in fact 0. Clicking on the checkboxes everything works fine as expected.
代码: UserControl-在命名空间ProgBarChkBxs中:
Code: UserControl - within namespace ProgBarChkBxs:
public partial class ucChkBoxes : UserControl
{
#region CbCount
public static readonly DependencyProperty CbCountProperty =
DependencyProperty.Register("CbCount", typeof(double), typeof(ucChkBoxes),
new FrameworkPropertyMetadata((double)0));
/// <summary>
/// Gets or sets the CbCount property. This dependency property
/// indicates the number of checkBoxes
/// </summary>
public double CbCount
{
get { return (double)GetValue(CbCountProperty); }
private set { SetValue(CbCountProperty, value); }
}
#endregion
double _totalCount = 0;
double _numberChecked = 0;
double DEFAULT = 0;
public ucChkBoxes()
{
InitializeComponent();
this.Tag = DEFAULT;
this.Loaded += new RoutedEventHandler(ucChkBoxes_Loaded);
}
void ucChkBoxes_Loaded(object sender, RoutedEventArgs e)
{
if (this.ourContainer.Children.Count != 0)
{
_totalCount = this.ourContainer.Children.Count;
}
this.CbCount = (double)_totalCount;
}
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
if (e.OriginalSource.GetType() == typeof(CheckBox))
{
CheckBox cb = (CheckBox)e.OriginalSource;
if (cb.IsChecked == true) { _numberChecked++; }
if (cb.IsChecked != true) { _numberChecked--; }
//simple POC progress metric
this.Tag = (double)(_numberChecked / _totalCount * _totalCount);
}
}
}
XAML:
<UserControl x:Class="ProgBarChkBxs.ucChkBoxes"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="Auto" Width="Auto">
<StackPanel>
<TextBlock Text="Please select options" ></TextBlock>
<StackPanel Name="ourContainer"
CheckBox.Checked="CheckBox_Checked"
CheckBox.Unchecked="CheckBox_Checked">
<CheckBox>Fruit Juice</CheckBox>
<CheckBox>Coffee</CheckBox>
<CheckBox>Toast</CheckBox>
<CheckBox>Cereal</CheckBox>
<CheckBox>Grapefruit</CheckBox>
</StackPanel>
</StackPanel>
</UserControl>
仅具有数据绑定的客户端是一个简单的窗口-下面的本地名称空间是指项目名称空间xmlns:local ="clr-namespace:ProgBarChkBxs",代码的内容是:
The Client which just has the databindings is a simple window - the local namespace below refers to the project namespace xmlns:local="clr-namespace:ProgBarChkBxs", the meat of the code is:
<StackPanel>
<local:ucChkBoxes x:Name="chkBoxes"/>
<ProgressBar Name="pb" Background="Azure" Minimum="0" Height="30"
Value="{Binding ElementName=chkBoxes,Path=Tag }"
Maximum="{Binding ElementName=chkBoxes,Path=CbCount }"
/>
</StackPanel>
真正奇怪的是,如果在CbCount的DP定义中,如果我将FrameworkPropertyMetadata更改为一个很小的值,说(double)0.001,那么问题就消失了.
The really weird thing is if within the DP definition of the CbCount if I change the FrameworkPropertyMetadata to a really small value to say (double)0.001 the problem goes away.
我正在XP上运行它.
非常感谢所有帮助-谢谢.
All help gratefully received - thanks.
更新: 当我着我的脚(谁说过要命!)时,我就一直在研究它.
Update: I have been digging into this again as it gnaws at my sole (who said get a life!)
我所做的事情:
1)添加一个类似progressBar的滑块,它也可以从RangeBase继承下来,这给了我预期的行为.
1) Adding a slider which also like progressBar inherits from RangeBase gives me the expected behaviour.
2)旋转反射器我可以看到ProgressBar的静态ctor首先将默认值设置为100, RangeBase.MaximumProperty.OverrideMetadata(typeof(ProgressBar),新的FrameworkPropertyMetadata(100.0));应该采取措施吗? 而在滑块中: RangeBase.MaximumProperty.OverrideMetadata(typeof(Slider),新的FrameworkPropertyMetadata(10.0,FrameworkPropertyMetadataOptions.AffectsMeasure));
2) Spinning up reflector I can see the static ctor for ProgressBar sets the default value first to 100, RangeBase.MaximumProperty.OverrideMetadata(typeof(ProgressBar), new FrameworkPropertyMetadata(100.0)); Should AffectMeasure? whereas in the slider: RangeBase.MaximumProperty.OverrideMetadata(typeof(Slider), new FrameworkPropertyMetadata(10.0, FrameworkPropertyMetadataOptions.AffectsMeasure));
3)因此,在设置ProgressBar.Value之后,我们需要另一次布局传递 返回到我的简单POC应用程序,如果在客户端窗口中的progressBar加载的处理程序中,则在第一次运行时我会调整布局:
3) So we need another layout pass after a I set the ProgressBar.Value Going back to my simple POC application if within a the progressBar loaded handler in the client window I jig the layout on the first run through:
this.Width += 1; //trigger another layout pass
然后,嘿,保存它.
这是一个错误吗?
我仍然不完全了解从最小值和最大值中计算出的progressBar值如何受到这种方式的影响,而不是对Slider的方式有何影响-Maximum的默认值似乎正在起作用,并且看起来好像ProgressBar默认值会影响度量通过. (缺少FrameworkPropertyMetadataOptions.AffectsMeasure
.)
I still do not fully understand though how the progressBar value which is calculated from Minimum and Maximum values is affected in this way and not the Slider - the default value of Maximum appears to be having an effect and it looks as if the ProgressBar default should affect the measure pass. (missing FrameworkPropertyMetadataOptions.AffectsMeasure
.)
任何人都可以帮忙,要么确认我的想法,要么解释这里的实际情况?
推荐答案
ucChkBoxes_Loaded方法.渲染进度条时,Tag和CbCount为零,这意味着进度条将具有min = 0,max = 0和value = 0(正确绘制为100%).如果您使进度条无效,例如调整大小窗口,它将显示为0%,因为现在Tag和CbCount已更新.
ucChkBoxes_Loaded method gets called after the progressbar gets rendered. When the progressbar gets rendered, Tag and CbCount are zero meaning that the progressbar will have min=0, max=0 and value=0, which is correctly drawn as as 100%. If you invalidate the progressbar, for example resize window it will show as 0%, since now Tag and CbCount have been updated.
要解决此问题,请不要等到调用ucChkBoxes.Loaded()初始化控件,在构造函数中进行初始化或在初始化DP for CbCount时进行此操作.
To fix, don't wait until ucChkBoxes.Loaded() is called to initialize your control, do it in constructor or when initializing the DP for CbCount, for example.
public ucChkBoxes()
{
InitializeComponent();
this.Tag = DEFAULT;
if (this.ourContainer.Children.Count != 0)
{
_totalCount = this.ourContainer.Children.Count;
}
this.CbCount = (double)_totalCount;
}
这篇关于此WPF ProgressBar奇数渲染行为是否是Bug?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!