这个WPF ProgressBar Odd呈现行为是一个Bug吗?

时间:2009-12-05 16:31:48

标签: wpf layout rendering progress-bar

希望有人可以提供帮助。 我有一个简单的场景,点击复选框正在WPF中推动进度条。复选框包含在UserControl中,进度条位于简单的WPF客户端窗口中。 在用户控件上我使用两个依赖属性: 1)现有的Tag属性具有我希望绑定到进度条值的值 2)一个名为CbCount的DP,它代表复选框的总数。

问题: 当应用程序运行时,进度条的进度显示为100%完成,即使通过Snoop我可以看到该值实际为0.单击复选框一切正常,因为预期。

代码: UserControl - 在命名空间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”,代码的内容是:

<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更改为一个非常小的值来说(双倍)0.001,问题就会消失。

我在XP上运行它。

感谢所有的帮助 - 谢谢。

更新 我一直在挖掘它,因为它啃着我的唯一(谁说要过生活!)

我做的事情:

1)添加一个滑块,它也像progressBar继承自RangeBase,给我预期的行为。

2)旋转反射器我可以看到ProgressBar的静态ctor首先将默认值设置为100, RangeBase.MaximumProperty.OverrideMetadata(typeof(ProgressBar),new FrameworkPropertyMetadata(100.0));应该影响吗? 而在滑块中: RangeBase.MaximumProperty.OverrideMetadata(typeof(Slider),new FrameworkPropertyMetadata(10.0,FrameworkPropertyMetadataOptions.AffectsMeasure));

3)因此,在设置ProgressBar.Value之后,我们需要另一个布局传递 回到我的简单POC应用程序,如果在客户端窗口中的progressBar加载处理程序中,我在第一次运行时浏览布局:

this.Width += 1; //trigger another layout pass

然后,嘿,presto它的工作原理。

这是一个错误吗?

我仍然不完全理解虽然以最小值和最大值计算的progressBar值如何以这种方式受影响而不是Slider - 默认值Maximum似乎有效,看起来好像ProgressBar默认应该影响度量传递。 (缺少FrameworkPropertyMetadataOptions.AffectsMeasure。)

任何人都可以帮忙,要么确认我的想法,要么解释这里发生的事情?

1 个答案:

答案 0 :(得分:1)

在呈现进度条后调用ucChkBoxes_Loaded方法。渲染进度条时,Tag和CbCount为零意味着进度条将具有min = 0,max = 0和value = 0,这被正确绘制为100%。如果您使进度条无效,例如调整大小窗口它将显示为0%,因为现在Tag和CbCount已更新。

要修复,请不要等到调用ucChkBoxes.Loaded()来初始化控件,在构造函数中执行此操作或在初始化DP for CbCount时执行此操作。

public ucChkBoxes()
{
    InitializeComponent();
    this.Tag = DEFAULT;
    if (this.ourContainer.Children.Count != 0)
    {
        _totalCount = this.ourContainer.Children.Count;
    }
    this.CbCount = (double)_totalCount;
}