0

I'm messing around with WPF and creating User Controls but having a hard time understanding how the databinding is supposed to work. Data binding seems to be overly complex and as long as WPF has been out I would think MS would've created some shortcuts to prevent having to do so much boilerplate code.

User control xaml

<UserControl x:Class="WPFTest.FancyBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d">
   <DockPanel>
      <Label Content="{Binding MyText}"></Label>
   </DockPanel>
</UserControl>

User control .cs

public partial class FancyBox : UserControl
{
    public static readonly DependencyProperty MyTextProperty = DependencyProperty.Register("MyText", typeof(string), typeof(FancyBox), new PropertyMetadata(null));

    public string MyText
    {
        get => (string)GetValue(MyTextProperty);
        set => SetValue(MyTextProperty, value);
    }

    public FancyBox()
    {
        InitializeComponent();
    }
}

Usage in my main window

<StackPanel>
    <local:FancyBox MyText="testing!"/>
</StackPanel>
user3953989
  • 1,844
  • 3
  • 25
  • 56
  • You should have a DataContext: https://stackoverflow.com/a/5077461/1410501. Does this solve your problem? – Ozkan Mar 09 '19 at 06:33
  • I tried using a viewmodel and the databinding but couldn't get that to work either. I also read that controls "shouldn't" have data-binding on them – user3953989 Mar 09 '19 at 16:24

2 Answers2

1

The binding Content="{Binding MyText}" is binding to the DataContext of the control (Label) which is inherited from closest ancestor up the tree who have one (your code doesn't show any DataContext assignment)

Your intended behavior is for Label's Content to bind to the User Control's Property in this case you need to make the user control your source. Many ways to do this for example:

<UserControl x:Class="WPFTest.FancyBox"
x:Name="RootElement"
....
<Label Content="{Binding MyText, Source={x:Reference RootElement} />

Or another way:

<Label Content="{Binding MyText, RelativeSource={RelativeSource FindAncestor,
    AncestorType={x:Type local:FancyBox}}" />

Keep in mind any Bindings without a source (Source, RelativeSource) will source from DataContext.

Mohammad
  • 1,930
  • 1
  • 21
  • 31
  • Thanks for the reply. So I was trying to Bind without a datacontext! This makes much more sense now. My solution above works and seems to be the most simple since binding appearently wasn't needed at all. +1 for the great explanation. – user3953989 Mar 09 '19 at 21:21
  • 1
    Yes. Bindings use DataContext as a source by default. If you want something other than the DataContext you need to provide an explicit Source or RelativeSource property so that WPF binds to the specified property of that source. Yes code-behind is ok as well. Keep the binding solution in mind in case you need to use MVVM patterm in future to fully isolate view/presentation related concerns which is helpful especially in larger projects. – Mohammad Mar 11 '19 at 09:38
0

I guess I didn't need data binding for this at all

I changed my controls label to:

<Label x:Name="lblText"></Label>

and my code-behind to:

public string MyText
{
     get => lblText.Content.ToString();
     set => lblText.Content = value;
}
user3953989
  • 1,844
  • 3
  • 25
  • 56