2

我正在尝试做一些简单的事情——创建一个 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 以强制属性更改通知,但该值永远不会在初始加载时设置。我可以改变价值观,看到一切都很好,但这是第一次什么都没有发生。

4

3 回答 3

1

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

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

DP 中的所有工作(动画、绑定等)都直接通过调用 SetValue 和 GetValue 进行。

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

注意: 附加属性(即使用RegisterAttached而不是)在解析 XAML 时Register实际上确实使用了设置器,但这是另一回事,因为普通 DP 不这样做。

更新:

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

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

于 2012-06-07T11:18:34.920 回答
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 对象),则默认值将是枚举的默认值。在我上面的示例中,这将是“正常”。现在,如果您尝试在创建控件时将值设置为 Normal,则不会调用回调,因为该值已经等于该值。

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

希望这有助于解决它!

于 2012-06-07T19:14:13.390 回答
0

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

<UI:PriorityControl Grid.Column="8" 
                    Priority="{Binding Path=Priority, Mode=TwoWay}" 
                    VerticalAlignment="Center"/>
于 2012-06-07T09:39:30.183 回答