11

I am trying to bind a dependency property via XAML to my custom WPF control.

Here's how I register the dependency property:

public static readonly DependencyProperty AltNamesProperty = 
    DependencyProperty.Register ("AltNames", typeof(string), typeof(DefectImages));

public string AltNames
{
    get { return (string) GetValue(AltNamesProperty); }
    set { SetValue(AltNamesProperty, value); }
}

And Here's how I call it in my XAML:

<DataGrid.Columns>                
    <DataGridTemplateColumn IsReadOnly="True">
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <StackPanel Name="StackPanel1" Grid.Column="0" Width="950">
                    <TextBlock FontSize="16" TextDecorations="None" Text="{BindingPath=StandardName}" Foreground="Black"  FontWeight="Bold" Padding="5,10,0,0"></TextBlock>
                    <TextBlock Text="{Binding Path=AltNames}"TextWrapping="WrapWithOverflow" Padding="5,0,0,10"></TextBlock>
                    <!-- this part should be magic!! -->
                    <controls:DefectImages AltNames="{Binding Path=AltNames}"></controls:DefectImages>
                </StackPanel>
            </DataTemplate>
        </DataGridTemplateColumn.CellTemplate>
    </DataGridTemplateColumn>
</DataGrid.Columns>

I know the AltNames property that I'm attempting to bind to is a valid property because I can display it in a textblock just fine. Am I registering the Dependency property incorrectly?

What do I need to do to get the correct value assigned to AltNames in my code behind?

CD Smith
  • 6,597
  • 7
  • 40
  • 66
jacobsimeon
  • 2,012
  • 1
  • 18
  • 20
  • Have you tried `AltNames="{Binding Path=AltNames, Mode=TwoWay}"`? Are there any binding errors in the output window during runtime? – nemesv Jun 01 '12 at 21:20
  • @nemesv just tried the two way binding, with no luck. There are no binding errors in the output window. – jacobsimeon Jun 01 '12 at 21:26
  • It is likely this is getting confused by 2 properties sharing the same name. Did you try renaming one? The workaround you flagged as an answer seems whacky! – Gusdor Jun 07 '13 at 10:32
  • In my case, the property was not set inside my `UserControl`'s constructor, but it was in the `Loaded` event. – Walter Stabosz Jan 23 '18 at 20:25

2 Answers2

21

Thanks to @Danko for getting me started. I registered a callback to set the value when the property changes.
Here's what I finally ended up with:

private static void OnDefectIdChanged(DependencyObject defectImageControl, DependencyPropertyChangedEventArgs eventArgs)
{
  var control = (DefectImages) defectImageControl;
  control.DefectID = (Guid)eventArgs.NewValue;
}

/// <summary>
/// Registers a dependency property, enables us to bind to it via XAML
/// </summary>
public static readonly DependencyProperty DefectIdProperty = DependencyProperty.Register(
    "DefectID",
    typeof (Guid),
    typeof (DefectImages),
    new FrameworkPropertyMetadata(
      // use an empty Guid as default value
      Guid.Empty,
      // tell the binding system that this property affects how the control gets rendered
      FrameworkPropertyMetadataOptions.AffectsRender, 
      // run this callback when the property changes
      OnDefectIdChanged 
      )
    );

/// <summary>
/// DefectId accessor for for each instance of this control
/// Gets and sets the underlying dependency property value
/// </summary>
public Guid DefectID
{
  get { return (Guid) GetValue(DefectIdProperty); }
  set { SetValue(DefectIdProperty, value); }
}
jacobsimeon
  • 2,012
  • 1
  • 18
  • 20
2

Maybe you need to specify the PropertyMetadata argument to DependencyProperty.Register, if the property affects how the control is rendered. For example:

DependencyProperty.Register("AltNames", typeof(string), typeof(DefectImages), 
                              new FrameworkPropertyMetadata( null,
                              FrameworkPropertyMetadataOptions.AffectsRender ) );
Danko Durbić
  • 7,077
  • 5
  • 34
  • 39
  • Tried this, and it's still not going for me. I placed a breakpoint on the setter for the AltNames property and it never gets executed. – jacobsimeon Jun 01 '12 at 22:37
  • 2
    Well, the setter is actually never executed, because binding is performed "behind the scenes". You could try [this PropertyMetadata constructor](http://msdn.microsoft.com/en-us/library/ms557327.aspx) to specify a callback method which is executed when the property is changed. Also, check out [How can I debug WPF bindings?](http://bea.stollnitz.com/blog/?p=52). – Danko Durbić Jun 01 '12 at 22:48
  • that's exactly what I just did. Using the callback to set the value worked for me. Thanks for getting me on the right track. – jacobsimeon Jun 01 '12 at 22:57
  • 1
    yeah but that means we have to use callback each time want to bind to DP ? and that sucks, if you have like 10 DP you will have to have 10 callback , the dp are set in the order you set them in xaml so we can't rely on the fact that if one dp is set other will be as well casue it is not the case. Loaded event is not go either cause bindings are already fired by then. – IronHide Sep 09 '22 at 14:47