How to implement WPF Binding programmatically (not XAML) with TwoWay binding mode?

Jörg Debus 96 Reputation points
2023-01-19T16:09:47.65+00:00

I have implemented some Dependency Properties in a c# class A as documented to mimic a very simple Control. In class B the Bindings and CLR Properties are implemented using the INotifyPropertyChange interface. Sending data from B to A works fine with binding mode OneWay. Sending data from B to A for updating and receiving the changed data back in B using the same DP with TwoWay mode results in the original data from B sent back from A.

Some help how to code the Receive/Update/Sentback logic in class A is highly appreciated.

Regards

Jörg

Developer technologies Windows Presentation Foundation
Developer technologies .NET Other
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Hui Liu-MSFT 48,676 Reputation points Microsoft External Staff
    2023-01-20T03:26:06.4066667+00:00

    You could refer to the following code.

    Custom Control:

    public class AControl1 : Control
        {
            public static readonly DependencyProperty TestPropProperty =
            DependencyProperty.Register("TestProp", typeof(string), typeof(AControl1), new UIPropertyMetadata(null));
    
            public string TestProp
            {
                get { return (string)GetValue(TestPropProperty); }
                set { SetValue(TestPropProperty, value); }
            }
    
            static AControl1()
            {
                DefaultStyleKeyProperty.OverrideMetadata(typeof(AControl1), new FrameworkPropertyMetadata(typeof(AControl1)));
            }
        }
    
    
    
    
    
    
    

    Generic.xaml:

    <ResourceDictionary
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DatabindingCodebehind">
    
    
        <Style TargetType="{x:Type local:AControl1}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:AControl1}">
                        <Border Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="{TemplateBinding BorderThickness}">
                            <StackPanel>
                                <TextBlock Text="Testing..."  Height="50"/>
                                <Separator />
                                <Label Height="50" Content="{Binding TestProp, RelativeSource={RelativeSource Mode=TemplatedParent}}"  />
                            </StackPanel>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ResourceDictionary>
    

    MainWindow.xaml:

    <Grid x:Name="grid">
    </Grid>
    

    MainWindow.xaml.cs:

    
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Data;
    using System.Windows.Media;
    
    namespace DatabindingCodebehind
    {
        public partial class MainWindow : Window,INotifyPropertyChanged
        {
    
            AControl1 a = new AControl1();
            public MainWindow()
            {
                InitializeComponent();
                grid.Children .Add (a);
                a.Height = 150;
                a.Width = 100;
                a.Background = Brushes.AliceBlue;
                TestObject myDataObject = new TestObject("name1");
                Binding myBinding = new Binding("Name");
                myBinding.Source = myDataObject;
                myBinding.Mode = BindingMode.TwoWay;
                a.SetBinding(AControl1.TestPropProperty, myBinding);
            }
            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged([CallerMemberName] string name = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
            }
        }
    
        public class TestObject : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            protected void OnPropertyChanged(string PropertyName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
            public TestObject() { }
            public TestObject(string Name) 
            {
                _Name = Name;
            }
            private int _id;
            public int Id
            {
                get { return _id; }
                set { _id = value; OnPropertyChanged("Id"); }
            }
    
            private string _Name;
            public string Name
            {
                get { return _Name; }
                set { _Name = value; OnPropertyChanged("Name"); }
            }
        }
    }
    
    

    The result:

    User's image


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.