I’m trying to do something simple — make a DependencyProperty and then bind to it. However, the getter doesn’t appear to fire when I start up the app. (I’m guessing the solution will make me smack my head and go “Doh!”, but still. 🙂 )
Any ideas?
Code-behind code:
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); }
}
Control 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>
Binding statement:
<UI:PriorityControl Grid.Column="8"
Priority="{Binding Path=Priority}"
VerticalAlignment="Center"/>
Some other notes:
- Binding is in a UserControl
- UserControl contains the PriorityControl
- PriorityControl contains the DependencyProperty
- I’ve checked that the data the UserControl is getting the appropriate data — every other binding works.
- If I change the selection on the PriorityControl via the mouse, everything fires as appropriate. It’s just that initial setting of the value that isn’t working.
- Priority is an enum.
EDIT: I’ve tried two additional things. First, I made the binding to the value two-way, but that didn’t work. Then, I added a property changed callback to the dependency property and made it call OnPropertyChanged, like so:
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");
}
That didn’t work either. I even tried overriding ApplyTemplate on the control to force a property change notification, but the value is never getting set on initial load. I can change values and see everything fire just fine, but it’s that first time that nothing is coming through.
The getter and setter for a DependencyProperty are not called by anyone except you!
They are simply helpers generated for your benefit (to save you lots of casting and calls to GetValue/SetValue).
All work in DPs (animation, binding etc) happens directly via calls to SetValue and GetValue.
If you need to catch a change in value, provide the change callback in the Register call.
Note: Attached properties (i.e. using
RegisterAttachedinstead ofRegister) actually do use the setter, while parsing the XAML, but that is another story as normal DPs do not.Update:
You have not set a default value in your Register, so it defaults to 0 (which is your enum value “Normal”). If you set that as the first value in your binding there is not change so it won’t trigger.
One Solution: Add a “none” enum as your first 0 value, so that “Normal” (value 1) will cause a change. Alternatively set a default value in the Register that is not “Normal”.