此WPF ProgressBar奇数渲染行为是否是Bug? [英] Is this WPF ProgressBar Odd render behaviour a Bug?

查看:58
本文介绍了此WPF ProgressBar奇数渲染行为是否是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆