DependencyProperty绑定不会在初始加载时发生

时间:2012-06-06 22:36:38

标签: silverlight dependency-properties

我正在尝试做一些简单的事情 - 创建一个DependencyProperty然后绑定到它。但是,当我启动应用程序时,getter似乎没有触发。 (我猜这个解决方案会让我咂嘴,然后去“Doh!”,但仍然。:))

有什么想法吗?

代码隐藏代码:

public static readonly DependencyProperty PriorityProperty = 
        DependencyProperty.Register("Priority", 
        typeof (Priority), typeof (PriorityControl), null);

public Priority Priority
{
    get { return (Priority)GetValue(PriorityProperty); }
    set { SetValue(PriorityProperty, value); }
}

控制XAML:

<ListBox Background="Transparent" 
         BorderThickness="0" 
         ItemsSource="{Binding Path=Priorities}" 
         Name="PriorityList" 
         SelectedItem="{Binding Path=Priority, Mode=TwoWay}">
  <ListBox.ItemTemplate>
    <DataTemplate>
        <Grid Height="16" Width="16">
          <Border BorderBrush="Black"
                  BorderThickness="2"
                  CornerRadius="3"
                  Visibility="{Binding RelativeSource=
                       {RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=IsSelected, Converter={StaticResource boolToVisibilityConverter}}" />
          <Border CornerRadius="3" Height="12" Width="12">
            <Border.Background>
              <SolidColorBrush Color="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBoxItem}, Path=Content, Converter={StaticResource priorityToColorConverter}}" />
            </Border.Background>
          </Border>
        </Grid>
    </DataTemplate>
   </ListBox.ItemTemplate>
   <ListBox.ItemsPanel>
     <ItemsPanelTemplate>
       <StackPanel Orientation="Horizontal"/>
     </ItemsPanelTemplate>
   </ListBox.ItemsPanel>
 </ListBox>

绑定声明:

<UI:PriorityControl Grid.Column="8" 
                    Priority="{Binding Path=Priority}" 
                    VerticalAlignment="Center"/>

其他一些说明:

  • 绑定在UserControl中
  • UserControl包含PriorityControl
  • PriorityControl包含DependencyProperty
  • 我已经检查过UserControl获取相应数据的数据 - 每个其他绑定都有效。
  • 如果我通过鼠标更改了PriorityControl上的选项,则所有内容都会根据需要触发。只是初始设置的值不起作用。
  • 优先级是枚举。

编辑:我已经尝试了两件事。首先,我双向绑定了值,但这没有用。然后,我将一个属性更改回调添加到依赖项属性并使其调用OnPropertyChanged,如下所示:

public static readonly DependencyProperty PriorityProperty =
        DependencyProperty.Register("Priority", typeof (Priority), typeof (PriorityControl), new PropertyMetadata(HandleValueChanged));

private static void HandleValueChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
   var npc = dependencyObject as PriorityControl;
   npc.OnPropertyChanged("Priority");
}

这也不起作用。我甚至尝试在控件上覆盖ApplyTemplate以强制执行属性更改通知,但是在初始加载时永远不会设置该值。我可以改变价值观,看到一切都很好,但这是第一次没有任何事情发生。

3 个答案:

答案 0 :(得分:1)

除了之外的任何人都不会调用DependencyProperty的getter和setter!

它们只是为了您的利益而生成的帮助程序(为了节省大量的转换和对GetValue / SetValue的调用)。

DP中的所有工作(动画,绑定等)都是通过调用SetValue和GetValue直接发生的。

如果您需要捕获值的更改,请在注册调用中提供更改回调。

注意: 附加属性(即使用RegisterAttached代替Register)实际上在解析XAML时确实使用了setter, ,但这是another story,正常的DP不会。

更新

您没有在Register中设置默认值,因此它默认为0(这是您的枚举值“Normal”)。如果将其设置为绑定中的第一个值,则不会更改,因此不会触发。

一个解决方案:添加“无”枚举作为您的前0值,以便“正常”(值1)将导致更改。或者在寄存器中设置一个非“正常”的默认值。

答案 1 :(得分:1)

我注意到,在执行依赖项属性时,如果在属性定义期间已经设置了值,则它将无法正确执行。您已经说过在应用程序中设置值时没有问题,因此我将假设没有管道问题。

考虑以下示例:

<强> XAML

<UI:PriorityControl Priority="{Binding Path=Priority, Mode=TwoWay}"/>

<强>代码

public enum Priority
{
    Normal,
    Low,
    High
}

public class PriorityControl : UserControl
{    
    public static readonly DependencyProperty PriorityProperty =
      DependencyProperty.Register("Priority", typeof(Priority), typeof(PriorityControl), new PropertyMetadata(DependencyProperty.UnsetValue, OnPriorityPropertyChanged);

    public Priority Priority
    {
        get { return (Priority)this.GetValue(PriorityProperty); }
        set { this.SetValue(PriorityProperty, value); }
    }

    private static void OnPriorityPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
    {
        PriorityControl control = sender as PriorityControl;
        if (control != null)
        {
            // Do what you wanted to here.
        }
    }
}

如果您正在使用枚举,并且没有指定默认值(在创建时未通过向依赖项属性提供PropertyMetadata对象而出现这种默认值),则默认值将为枚举值的默认值。 ; s默认值。在我上面的例子中,&#34; Normal&#34;。现在,如果您在创建控件时尝试将值设置为Normal,则不会调用回调,因为该值已经等于该值。

为了使其正常工作,您必须像我在定义属性时所做的那样将DependencyProperty.UnsetValue传递给PropertyMetadata对象。这将允许在最初设置值时调用OnPriorityPropertyChanged方法。

希望有助于解决它!

答案 2 :(得分:0)

不是100%肯定,但可能就像将Priority绑定更改为TwoWay一样简单。

<UI:PriorityControl Grid.Column="8" 
                    Priority="{Binding Path=Priority, Mode=TwoWay}" 
                    VerticalAlignment="Center"/>