-1

The problem is quite known and popular ...

I went through many threads today, but none of them allowed me to solve my problem, so I decided to ask you for help. I think I follow all the tips of other users...

CustomControl.xaml:

    <UserControl x:Class="X.UserControls.CustomUserControl"
             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"
             x:Name="eqAction"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">

    <StackPanel Orientation="Horizontal" VerticalAlignment="Center">
        <TextBlock Text="{Binding Path=FirstName, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    </StackPanel>
</UserControl>

CustomControl.xaml.cs:

public partial class CustomControl : UserControl
{
    public static readonly DependencyProperty FirstNameProperty = DependencyProperty.Register(
        "FirstName",
        typeof(string),
        typeof(CustomControl),
        new FrameworkPropertyMetadata(default(string),
            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

    public string FirstName
    {
        get
        {
            return (string)GetValue(FirstNameProperty);
        }
        set
        {
            SetValue(FirstNameProperty, value);
        }
    }

    public CustomControl()
    {
        InitializeComponent();
    }
}

MainViewModel.cs:

    private string _test;
    public string Test
    {
        get { return _test; }
        set
        {
            _test = value;
            OnPropertyChanged(string.Empty);
        }
    }

    public MainViewModel()
    {
        Test = "abc";
    }

    public new event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

MainUserControl.xaml

<StackPanel x:Name="NotWorking">
      <userControls:CustomControl FirstName="{Binding Path=Test, Mode=TwoWay}" />
</StackPanel>

<StackPanel x:Name="Working">
      <userControls:CustomControl FirstName="My string value that works" />
</StackPanel>

<StackPanel x:Name="WorkingToo">
      <TextBlock Text="{Binding Path=Test, Mode=TwoWay}" />
</StackPanel>
  • In my MainUserControl.xaml file I have three stackpanels. The first is what I want to achieve. Unfortunately, no data is currently binded (nothing displayed).

  • However, when instead of binding I assign a string value to the property, the text will be displayed correctly (example 2).

  • Example 3: when I create a binding to e.g. a textblock component, the text will also be displayed ... Only one control that appears in the first stackpanel (name NotWorking) works differently ...

Do you see the mistake?

SiSharp
  • 27
  • 5
  • 1
    A UserControl must not set its own DataContext. As a note, it makes no sense to have a TwoWay Binding on the Text property of a TextBlock. That Binding is inherently OneWay. It is therefore also pointless to set `UpdateSourceTrigger=PropertyChanged`. – Clemens Apr 19 '20 at 06:41

1 Answers1

1

the problem is the line where you set the datacontext in the MainUserControl:

DataContext="{Binding RelativeSource={RelativeSource Self}}"

When you set the DataContext as in your code, the binding in the MainUserControl will look for a property named Test in the CustomControl and not in the MainViewModel.

Clemens
  • 123,504
  • 12
  • 155
  • 268
Marlonchosky
  • 494
  • 5
  • 16