0

I tried to bind a UserControl in two-way mode, but there isn't any notification when the custom control is updated.

I used the following post to fix it up without success WPF usercontrol Twoway binding Dependency Property

When I update the main window control, the UserControl receives the data and displays the correct values. But when I update the UserControl, nothing changes in the main window.

MainWindow C#:

using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace WpfAppUserControl_Test1
{
    public partial class MainWindow : Window
    {
        TextBinding textBinding = new TextBinding();

        private class TextBinding : INotifyPropertyChanged
        {
            private string TextCtrlValue = "";

            public string TextCtrl
            {
                get { return TextCtrlValue; }
                set { TextCtrlValue = value; NotifyPropertyChanged("TextCtrl"); }
            }

            public event PropertyChangedEventHandler PropertyChanged;

            private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }

            private List<int> ComboListValue = new List<int>();

            public List<int> ComboList
            {
                get { return ComboListValue; }
                set { ComboListValue = value; NotifyPropertyChanged("ComboList"); }
            }

            public int ComboSelectedValue = 1;

            public int ComboSelected
            {
                get { return ComboSelectedValue; }
                set { ComboSelectedValue = value; NotifyPropertyChanged("ComboSelected"); }
            }
        }

        public MainWindow()
        {
            InitializeComponent();
            DataContext = textBinding;

            textBinding.ComboList.Add(1);
            textBinding.ComboList.Add(2);
            textBinding.ComboList.Add(3);
            textBinding.ComboList.Add(4);
            textBinding.ComboSelected = 1;
            textBinding.TextCtrl = "Foo";
        }
    }
}

MainWindow XAML :

<Window x:Class="WpfAppUserControl_Test1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfAppUserControl_Test1"
        mc:Ignorable="d"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="MainWindow" Height="181" Width="367">
    <Grid>
        <local:UserControlTest1
            TextValue="{Binding Path=TextCtrl, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
            ComboValues="{Binding Path=ComboList}"
            ComboSelected ="{Binding Path=ComboSelected, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
            HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top"/>
        <Rectangle HorizontalAlignment="Left" Height="116" Margin="189,10,0,0" Stroke="LightGray" VerticalAlignment="Top" Fill="LightGray" Width="146"/>
        <Label Content="Main Window" HorizontalAlignment="Left" Height="23" Margin="205,20,0,0" VerticalAlignment="Top" HorizontalContentAlignment="Center" Width="114"/>
        <TextBox
            Text="{Binding Path=TextCtrl, UpdateSourceTrigger=PropertyChanged}"
            HorizontalAlignment="Left" VerticalAlignment="Top" Width="114" Height="23" Margin="205,57,0,0" TextWrapping="Wrap"/>
        <ComboBox
            ItemsSource="{Binding Path=ComboList}"
            SelectedValue="{Binding Path=ComboSelected, UpdateSourceTrigger=PropertyChanged}"
            DisplayMemberPath="" SelectedValuePath=""
            HorizontalAlignment="Left" Margin="202,96,0,0" VerticalAlignment="Top" Width="120"/>
    </Grid>
</Window>

UserControl XAML :

<UserControl x:Class="WpfAppUserControl_Test1.UserControlTest1"
             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" 
             xmlns:local="clr-namespace:WpfAppUserControl_Test1"
             mc:Ignorable="d"
             Height="116" Width="139" Background="DarkGray">
    <Grid>
        <Label
            Content="User Control" HorizontalAlignment="Center" Height="28" Margin="0,10,0,0" VerticalAlignment="Top" HorizontalContentAlignment="Center" Width="119"/>
        <TextBox
            Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:UserControlTest1}}, Path=TextValue}"
            Margin="0,47,0,0" TextWrapping="Wrap"
            HorizontalAlignment="Center" VerticalAlignment="Top" Width="119" Height="20"/>
        <ComboBox
            ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:UserControlTest1}}, Path=ComboValues}"
            SelectedValue="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:UserControlTest1}}, Path=ComboSelected}"
            DisplayMemberPath="" SelectedValuePath=""
            HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0,84,0,0" Width="118"/>
    </Grid>
</UserControl>

UserControl C# :

using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace WpfAppUserControl_Test1
{
    public partial class UserControlTest1 : UserControl
    {
        public static readonly DependencyProperty TextValueProperty = DependencyProperty.Register("TextValue",
          typeof(string),
          typeof(UserControlTest1),
          //new PropertyMetadata(null));
          new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public string TextValue
        {
            get => (string)GetValue(TextValueProperty);
            set => SetValue(TextValueProperty, value);
        }
       
        public static readonly DependencyProperty ComboValuesProperty = DependencyProperty.Register("ComboValues",
        typeof(List<int>),
        typeof(UserControlTest1),
        new PropertyMetadata(null));

        public string ComboValues
        {
            get => (string)GetValue(ComboValuesProperty);
            set => SetValue(ComboValuesProperty, value);
        }

        public static readonly DependencyProperty ComboSelectedProperty = DependencyProperty.Register("ComboSelected",
            typeof(int),
            typeof(UserControlTest1),
          //new PropertyMetadata(null));
          new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public int ComboSelected
        {
            get => (int)GetValue(ComboSelectedProperty);
            set => SetValue(ComboSelectedProperty, value);
        }

        public UserControlTest1()
        {
            InitializeComponent();
        }
    }
}
newky2k
  • 419
  • 5
  • 12
Yaegaki2
  • 9
  • 4
  • There is `public string ComboValues` and `typeof(List)` in the ComboValuesProperty declaration, which won't fit. – Clemens Oct 22 '21 at 08:59
  • Also note that `DataContext="{Binding RelativeSource={RelativeSource Self}}"` in MainWindow.xaml is redundant, because you set the Window's DataContext in code behind. – Clemens Oct 22 '21 at 09:02
  • Instead of setting an empty SelectedValuePath and binding SelectedValue on the ComboBoxes, bind their SelectedItem property. – Clemens Oct 22 '21 at 09:04
  • Thank you. I fixed the mistakes you showed me that generated conflicts. From now the combobox works perfectly, but not the TextBox. It still keep the Main TextBox unchanged when i update the UserControl Textbox. – Yaegaki2 Oct 22 '21 at 11:16
  • Add `UpdateSourceTrigger=PropertyChanged` to the TextBox.Text Binding in the UserControl's XAML. A Binding of the TextBox.Text property is actually the only place where setting UpdateSourceTrigger may really be necessary. It is pointless to set it on the other Bindings. – Clemens Oct 22 '21 at 11:19
  • Ok, you're great !!! Another point i missed – Yaegaki2 Oct 22 '21 at 11:27

0 Answers0