Надеюсь, кто-нибудь может помочь.
У меня есть простой сценарий, в котором при нажатии флажков отображается индикатор выполнения в WPF . Флажки содержатся в UserControl, а индикатор выполнения находится в простом окне клиента WPF.
На пользовательском элементе управления я использую два свойства зависимости:
1) существующее свойство Tag имеет значение, которое я хочу связать со значением индикатора выполнения, и
2) DP под названием CbCount, который представляет общее количество флажков.
Проблема:
Когда приложение запускается, индикатор выполнения отображается как выполненный на 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>
Действительно странная вещь, если в определении DP CbCount, если я изменю FrameworkPropertyMetadata на действительно маленькое значение, чтобы сказать (удвоить) 0,001, проблема исчезнет.
Я запускаю это на XP.
Вся помощь с благодарностью получена - спасибо.
Обновление:
Я снова копался в этом, так как он грызет мою подошву (кто сказал, возьми жизнь!)
То, что я сделал:
1) Добавление ползунка, который также, как progressBar наследует от RangeBase, дает мне ожидаемое поведение.
2) Вращающийся отражатель. Я вижу, что статический ctor для ProgressBar сначала устанавливает значение по умолчанию равным 100,
RangeBase.MaximumProperty.OverrideMetadata (typeof (ProgressBar), новый FrameworkPropertyMetadata (100.0)); Должен ли AffectMeasure?
тогда как в слайдере:
RangeBase.MaximumProperty.OverrideMetadata (typeof (Slider), новый FrameworkPropertyMetadata (10.0, FrameworkPropertyMetadataOptions.AffectsMeasure));
3) Итак, нам нужен еще один проход макета после того, как я установил ProgressBar.Value
Возвращаясь к моему простому POC-приложению, если в загруженном обработчике progressBar в окне клиента я перетаскиваю макет при первом запуске:
this.Width += 1; //trigger another layout pass
Тогда, эй, просто это работает.
Так это ошибка?
Я до сих пор не до конца понимаю, как таким образом влияет значение progressBar, которое вычисляется из минимальных и максимальных значений, а не ползунок - значение по умолчанию Максимальное, похоже, оказывает влияние и выглядит так, как будто ProgressBar значение по умолчанию должно влиять на проход измерения. (отсутствует FrameworkPropertyMetadataOptions.AffectsMeasure
.)
Может ли кто-нибудь помочь, подтвердить мои мысли или объяснить, что на самом деле здесь происходит?