Binding main class fails

i created a custom control in WPF for Windows 10 Apps. The problem is that the binding in the main class doesn't work. It binds to my custom control. Can anyone see the problem? How can i repair the code. It doesnt work. Specially the binding doesnt work. How can i solve that. I have no idea, how to fix that.

View Model Code

         using System;
        using System.Collections.Generic;
        using System.ComponentModel;
        using System.Linq;
        using System.Runtime.CompilerServices;
        using System.Text;
        using System.Threading.Tasks;
        using Windows.UI.Xaml;
        using AppDemo.Annotations;

        namespace AppDemo
        {
            public class ViewModel : INotifyPropertyChanged
            {
                private String t1, t2;
                public String T1
                {
                    get { return t1; }
                    set
                    {
                        t1 = value;
                        Concat = T1 + T2;
                    }
                }
                public String T2
                {
                    get { return t2; }
                    set
                    {
                        t2 = value;
                        Concat = T1 + T2;
                    }
                }

                private String concat;
                public String Concat
                {
                    get { return concat; }
                    set
                    {
                        concat = value;
                        OnPropertyChanged(nameof(Concat));
                    }
                }



                public event PropertyChangedEventHandler PropertyChanged;

                [NotifyPropertyChangedInvocator]
                protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
                {
                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));


                }
            }
        }
    <UserControl
        x:Class="AppDemo.ExampleControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:AppDemo"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d"
        d:DesignHeight="300"
        d:DesignWidth="400">

        <Grid Name="grid">
           <StackPanel>
               <TextBox Text="{Binding T1,Mode=TwoWay}"/>
               <TextBox Text="{Binding T2,Mode=TwoWay}"/>
            </StackPanel>
        </Grid>
    </UserControl>
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using AppDemo.Annotations;

// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236

namespace AppDemo
{
    public sealed partial class ExampleControl : UserControl
    {
        public static readonly DependencyProperty ConcatProperty = DependencyProperty.Register(
            "Concat", typeof(String), typeof(ExampleControl), new PropertyMetadata(default(String)));


        private ViewModel m;

        public String Concat
        {
            get { return (String)GetValue(ConcatProperty); }
            set { SetValue(ConcatProperty, value); }
        }

        public ExampleControl()
        {
            this.InitializeComponent();
            m = new ViewModel();
            grid.DataContext = m;
            m.PropertyChanged += M_PropertyChanged;
        }

        private void M_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Concat = m.Concat;
        }

        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}



<Page
    x:Class="AppDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:AppDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <local:ExampleControl Concat="{Binding C}"/>
        <Button Name="btnTest" Click="BtnTest_OnClick">Test</Button>
        </StackPanel>
    </Grid>
</Page>

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace AppDemo
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public String C { get; set; }

        public MainPage()
        {
            this.InitializeComponent();
            this.DataContext = this;
        }


        private void BtnTest_OnClick(object sender, RoutedEventArgs e)
        {
            String msg = C;
        }
    }
}

2 answers

  • answered 2018-07-12 07:04 James Hurst

    It is generally better to put your properties that you want to bind to, within their own distinct view-model class - not mixed in with your view code. This code is unnecessarily obtuse.

    BTW... Your UserControl named ExampleControl, has textboxes whose Text property is bound to T1 and T2. However, when you set either of those values - they set the Concat property but fail to raise the PropertyChanged event with their own name. You'd fix that with, for example:

    public String T1
    {
      set
      {
        t1 = value;
        OnPropertyChanged(nameof(T1));
        Concat = T1 + T2;
      }
    }
    

  • answered 2018-07-12 09:50 mm8

    Set the Mode of the Binding to TwoWay in your MainPage:

    <local:ExampleControl Concat="{Binding C, Mode=TwoWay}"/>