Reuben Reuben - 1 month ago 15
C# Question

Why does my implementation of WPF binding not work two-way?

I'm trying to create a template for WPF binding so that I can pull code from it whenever I need to use binding in the future. Currently binding isn't work either way.

I expect this code to display "MyString" and "MyInt" in the textboxs in the UI and to correctly change the logic when a user changes the value (hence the check buttons).

However, MyString and MyInt are not being displayed in the textboxes, nor does changing them actually change the values of the variables.

MainWindow.xaml.cs:

using System.Windows;
namespace WpfBindingTemplate
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
myController = new Controller();
}

Controller myController;

private void check_string(object sender, RoutedEventArgs e)
{
MessageBox.Show("MyString: " + myController.MyString);
}

private void check_int(object sender, RoutedEventArgs e)
{
MessageBox.Show("MyInt: " + myController.MyInt);
}
}
}


MainWindow.xaml:

<Window x:Class="WpfBindingTemplate.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:WpfBindingTemplate"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox Name="myTextBox" Text="{Binding Path=myController.MyString}" HorizontalAlignment="Left" Height="23" Margin="202,136,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<Label x:Name="label" Content="String binding:" HorizontalAlignment="Left" Margin="77,133,0,0" VerticalAlignment="Top" Width="104"/>
<Button x:Name="button" Content="string check" Click="check_string" HorizontalAlignment="Left" Margin="370,136,0,0" VerticalAlignment="Top" Width="75"/>
<Label x:Name="label1" Content="int binding:" HorizontalAlignment="Left" Margin="77,188,0,0" VerticalAlignment="Top" Width="94"/>
<TextBox x:Name="textBox" Text="{Binding Path=myController.MyInt}" HorizontalAlignment="Left" Height="23" Margin="202,190,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
<Button x:Name="button1" Click="check_int" Content="int check" HorizontalAlignment="Left" Margin="370,188,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Window>


Controller class:

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

namespace WpfBindingTemplate
{
public class Controller : INotifyPropertyChanged
{
public Controller()
{
MyString = "test string";
MyInt = 1;
}

public int MyInt { get; set; }

private string myString;
public string MyString { get { return myString; } set { SetProperty(ref myString, value); } }


public event PropertyChangedEventHandler PropertyChanged;
private void SetProperty<T>(ref T field, T value, [CallerMemberName] string name = "")
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
}
}

Answer

For starters, binding doesn't work against fields, you need to have a get/set on "Controller myController;" and it also needs to be public (under some conditions, it will work with internal as well).

Comments