2009-12-05 84 views
0

希望有人能幫忙。 我有一個簡單的場景,點擊複選框正在駕駛WPF中的進度條。複選框包含在UserControl中,進度欄位於簡單的WPF客戶端窗口中。 在用戶控件上,我使用了兩個依賴屬性: 1)現有的Tag屬性具有我希望綁定到進度欄值的值,並且2)一個名爲CbCount的DP,它表示複選框的總數。這是WPF ProgressBar Odd渲染行爲的一個Bug嗎?

問題: 當應用程序運行進度條的進度顯示爲100%完成,即使通過探聽我能看到的價值實際上是在0點擊複選框預期一切正常。

代碼: 用戶控件 - 命名空間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)紡絲向上反射鏡我可以看到所述靜態構造函數爲進度第一設置默認值100, RangeBase.MaximumProperty.OverrideMetadata(typeof運算(進度),新FrameworkPropertyMetadata(100.0));應該影響測量?在滑塊中: RangeBase.MaximumProperty.OverrideMetadata(typeof(Slider),new FrameworkPropertyMetadata(10.0,FrameworkPropertyMetadataOptions.AffectsMeasure));

3)因此,我們需要另一種佈局傳遞之後我設置了ProgressBar.Value 要回到我的簡單的POC應用程序,如果在客戶端窗口的進度加載處理程序中我經歷夾具在第一次運行的佈局:

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

然後,嘿,它的工作原理。

那麼這是一個錯誤?

我仍然不完全理解,但是如何從最小值和最大值計算出來的progressBar值以這種方式受到影響,而不是滑塊 - 最大值的默認值似乎具有效果,它看起來好像是ProgressBar默認應該會影響度量傳遞。 (缺少FrameworkPropertyMetadataOptions.AffectsMeasure。)

任何人都可以幫忙,或者確認我的想法或者解釋這裏發生了什麼?

+0

@Andrew - 我的編輯修復了你的代碼。把帖子轉回到版本2,你應該看到所有的代碼。 – ChrisF 2009-12-05 17:00:02

+0

克里斯 - 感謝 - 抱歉原諒我的無知第一天對StackOverFlow作出貢獻如何將帖子重新發布到版本2? – Andrew 2009-12-05 18:14:15

+0

@Andrew - 選擇「編輯」鏈接。在「Rev」頁面的頂部有一個下拉菜單。從列表中選擇所需的修訂,然後選擇「保存編輯」。 – ChrisF 2009-12-05 19:40:40

回答

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; 
} 
+0

謝謝你看到這個 - 是的,我意識到我可以把它移到ctor,並且將來會這樣做,並理解推理 - 但是,我期待改變DP CbCount會重新觸發計算最大值,然後內部觸發PB中的新佈局傳遞,min將爲0,max將爲5.這似乎與滑塊的行爲不同。 – Andrew 2009-12-07 22:31:34

+0

在加載控件後,看起來並不意味着要更改「最大值」。看到這個答案:http://stackoverflow.com/questions/655780/progressbar-not-updating-on-change-to-maximum-through-binding/656187 – 2009-12-08 03:10:47

+0

謝謝你清除了這個謎,我更新了代碼。所以PB最大值通過基類RangeBase中的DP進行更新,但是PB沒有做任何事情。 SetProgressBarIndicatorLength永遠不會被調用,因此渲染不會更新!這就解釋了爲什麼使用Snoop和DependencyPropertyHelper.GetValueSource我只能看到Maximum和Value已經更新,但沒有看到它,並且控件最終處於不一致的狀態。看起來像一個微妙的錯誤。 – Andrew 2009-12-08 15:28:39