Faerdan
Topic Author
Posts: 57
Joined: 02 Oct 2015, 09:11
Location: Galway, Ireland
Contact:

Binding to DependencyObject Properties

17 Feb 2021, 17:03

I want to pass some objects (of a particular type) to a DependencyProperty in XAML, and have the values of properties on those objects set via bindings.

I've tried a number of methods, but none have worked.

This was my latest attempt:
C#
public class ParameterDependencyObject : DependencyObject
{

    public static readonly DependencyProperty KeyProperty =
        DependencyProperty.Register(nameof(Key), typeof(string), typeof(ParameterDependencyObject), new PropertyMetadata(null));

    public static readonly DependencyProperty ValueProperty =
            DependencyProperty.Register(nameof(Value), typeof(string), typeof(ParameterDependencyObject), new PropertyMetadata(null));

    public string Key
    {
        get { return (string)GetValue(KeyProperty); }
        set { SetValue(KeyProperty, value); }
    }

    public string Value
    {
        get { return (string)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }
}

[ContentProperty("Parameters")]
public class TextParametersDependencyObject : DependencyObject
{
    public ObservableCollection<ParameterDependencyObject> Parameters
    {
        get { return (ObservableCollection<ParameterDependencyObject>)GetValue(ParametersProperty); }
        set { SetValue(ParametersProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Parameters.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ParametersProperty =
        DependencyProperty.Register("Parameters", typeof(ObservableCollection<ParameterDependencyObject>), typeof(TextParametersDependencyObject), new PropertyMetadata(null));

}
XAML:
<common:TextContentControl HorizontalAlignment="Center" VerticalAlignment="Center" Style="{StaticResource common_style_hermes_textShadowedNormal1}" Text="((common_txt_tripleInsertionTEST))" >
    <!-- TextContentControl has a TextParametersDependencyObject TextFormatParametersProperty -->
    <common:TextContentControl.TextFormatParameters>
        <viewModels:TextParametersDependencyObject>
            <!-- Works fine -->
            <viewModels:ParameterDependencyObject Key="Key1"  Value="This works"/>
            <!-- Error in Unity "StaticResource 'airshipHUD_string_test' not found." -->
            <viewModels:ParameterDependencyObject Key="Key2" Value="{StaticResource airshipHUD_string_test}" />
            <!-- Error in Unity "StaticResource 'airshipHUD_string_test' not found." -->
            <viewModels:ParameterDependencyObject Key="Key3" Value="{Binding CurrentSpeed}" />
        </viewModels:TextParametersDependencyObject>
    </common:TextContentControl.TextFormatParameters>
</common:TextContentControl>
Could you explain why this doesn't work? And perhaps suggest another method to achieve a similar result?

Thanks!

Tags:
 
User avatar
sfernandez
Site Admin
Posts: 2056
Joined: 22 Dec 2011, 19:20

Re: Binding to DependencyObject Properties

18 Feb 2021, 16:29

It is not working because the items in your collection are not part of the logical tree so resources and bindings can't walk up the tree to resolve the references.

You can use a FreezableCollection that automatically connects its items to the tree:
public class ParameterCollection : FreezableCollection<Parameter> { }

[ContentProperty("Parameters")]
public class ParameterList : DependencyObject
{
    public ParameterList()
    {
        Parameters = new ParameterCollection();
    }

    public ParameterCollection Parameters
    {
        get { return (ParameterCollection)GetValue(ParametersProperty); }
        set { SetValue(ParametersProperty, value); }
    }

    public static readonly DependencyProperty ParametersProperty = DependencyProperty.Register(
        "Parameters", typeof(ParameterCollection), typeof(ParameterList),
        new PropertyMetadata(null));
}

public class Parameter : DependencyObject
{
    public string Key
    {
        get { return (string)GetValue(KeyProperty); }
        set { SetValue(KeyProperty, value); }
    }

    public static readonly DependencyProperty KeyProperty = DependencyProperty.Register(
        "Key", typeof(string), typeof(Parameter),
        new PropertyMetadata(string.Empty));


    public string Value
    {
        get { return (string)GetValue(ValueProperty); }
        set { SetValue(ValueProperty, value); }
    }

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register(
        "Value", typeof(string), typeof(Parameter),
        new PropertyMetadata(string.Empty, OnValueChanged));

    private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        Parameter param = (Parameter)d;
        UnityEngine.Debug.Log($"Key={param.Key}, Value={e.NewValue}");
    }
}
 
Faerdan
Topic Author
Posts: 57
Joined: 02 Oct 2015, 09:11
Location: Galway, Ireland
Contact:

Re: Binding to DependencyObject Properties

18 Feb 2021, 19:03

This is excellent, thank you.
 
User avatar
jsantos
Site Admin
Posts: 3015
Joined: 20 Jan 2012, 17:18
Contact:

Re: Binding to DependencyObject Properties

22 Feb 2021, 14:28

Thanks! Marking as solved

Who is online

Users browsing this forum: No registered users and 1 guest