0

I have a data model (not really a view model; it does not directly contain dependency properties, and I want to keep it that way), which structurally looks something like this:

public class Foo
{
    public Bar Data { get; set; }
    // other properties
}

public class Bar
{
    public string Text { get; set; }
    // other properties
}

And a custom UserControl that looks somewhat like this:

<MyUserControl ...>
    <Grid>
        <TextBox Text="{Binding ???}">
    </Grid>
</MyUserControl>

The code-behind of the user control contains a reference to an instance of Foo.

How would I go about binding the Text value of the TextBox inside the MyUserControl to the Data.Text property of the Foo object referenced in the control?

Note:
I would like to avoid declaring a bunch of DPs inside the MyUserControl class as Foo references multiple other types, which respectively contain properties with the same name. So to stay consistent in naming the DPs, I would have to prefix every single one with something showing the nested property they belong to.


So far, I have tried attaching DependencyPropertys to my data model using a helper class with static Get/Set methods as follows:

using DP = System.Windows.DependencyProperty;

static class PropertyProvider
{
    
    public static readonly DP TextProperty = DP.RegisterAttached (
        "Text",
        typeof (string),
        typeof (Bar),
        new UIPropertyMetadata ("")
    );
    public static string GetText (DependencyObject obj) => (string)obj.GetValue (TextProperty);
    public static void SetText (DependencyObject obj, string value) => obj.SetValue (TextProperty, value);

}

This results in an XAML Binding Failure and also - after some reasearch - seems to be the wrong approach; I understood it thus far, DPs are supposed to be attached to the control instead instead of the data/view model.
That however leaves me questioning how the data from the control is supposed to be written to/read from the context object, if the DP were attached to the control.

Another thing I attempted, was to simply set the Foo instance as the MyUserControl's DataContext, and declaring the binding like this: Text="{Binding Data.Text}", which seemed to work here.
This also resulted in an XAML Binding Failure, because "Text property not found on object of type Foo".

Zenvin
  • 1
  • 1
  • 1
    "I would like to avoid declaring a bunch of DPs inside the MyUserControl" - then creating custom usercontrol loses its purpose. define DataTemplate[s] instead – ASh Dec 17 '22 at 20:47
  • I think you just misassigned something, the `DataContext` approach should work. "Text" is *not* a property on `Foo`, it's a property on `Bar` in order to use `Data.Text` as the binding statement, make sure sure the UserControl's constructor has `DataContext` set to an instance of Foo. After or before `InitializeComponent` shouldn't matter. I was unable to reproduce your error with a usercontrol and the foo/bar classes you supplied. The text showed up for me with `Data.Text` as the binding. Do you maybe have something else adjusting the datacontext somewhere else in the app? – AceGambit Dec 17 '22 at 20:49
  • 1
    @AceGambit, "make sure sure the UserControl's constructor has DataContext set to an instance of Foo" - this is a terrible antipattern. it causes way more problems than it is worth – ASh Dec 17 '22 at 20:52
  • @ASh DataTemplates are something I'll have to look into. Thanks for the pointer! – Zenvin Dec 17 '22 at 20:58
  • @ASh I guess I agree with that, typically when I'm doing WPF binding with DataContex's I use ViewModels, MVVM, DependencyInjection and set the DataContext using a `Binding` statement in the XAML at the user control level. @Zenvin, if all of that doesn't sound too daunting, I would definitely look into it, but @ASh is right, if all you want is to have some xaml that can display specific properties from a class, DataTemplates are likely the better approach. – AceGambit Dec 17 '22 at 21:06

0 Answers0