0

I can't seem to bind a control's value to an object. I want to bind a TextBox to a string object, the idea is that when textbox's text changes, it should automatically change the object as well. couldn't figure out what I'm doing wrong. Here is what I have tried:

MainWindow.xaml.cs:

public partial class MainWindow : Window
    {
        string str;
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = str;
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {

    }
}

and MainWindow.xaml:

<Window x:Class="WpfApp1.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:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="150" Width="150">
    <Grid Margin="0,0,642,319">
        <TextBox HorizontalAlignment="Left" Height="23"  TextWrapping="Wrap" Text="{Binding str}" VerticalAlignment="Top" Width="120" Margin="0,0,-120,-46" />
        <Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Click="Button_Click" Height="23" Margin="0,28,-75,-51" RenderTransformOrigin="0.423,2.257" />

    </Grid>
</Window>

So, when I enter something to the textbox and click the button, I should see the text in str while debugging but it is always null

hebele
  • 75
  • 9
  • You can access the TextBox in code behind directly if you assign a name to it: ``. In code behind: `var x = MyTextBox.Text` or `MyTextBox.Text = "Hello World"` – croxy Jun 12 '18 at 06:47
  • @croxy, Thanks, I know that. But the thing is, I have a full form consisting of 5-6 controls. I don't want to handle all of them separately at the end, manually. – hebele Jun 12 '18 at 06:50
  • This answer may help you: https://stackoverflow.com/a/6022711/5453249 – croxy Jun 12 '18 at 06:55
  • 1
    Start reading here: [Data Binding Overview](https://learn.microsoft.com/en-us/dotnet/framework/wpf/data/data-binding-overview). You should create a class with a public string property and assign an instance of it to the DataContext. – Clemens Jun 12 '18 at 07:08
  • Declare a public auto property for str - public string { get; set; } and set the DataContext = this; – Raviraj Palvankar Jun 12 '18 at 07:08
  • @RavirajPalvankar that worked, thanks! – hebele Jun 12 '18 at 07:17

3 Answers3

3
  1. Change the str to a auto property:

    public string str { get; set; }

  2. Change the DataContext to:

    DataContext = this;

The DataContext is the class which will hold your binding properties/commands/events. The properties/commands/events need to be public in order to be accessible by your view.

For the two-way binding to work, you have to notify to the UI binding that the property has been changed and for that you need to implement the INotifyPropertyChanged interface for the class which holds the properties which have been bound in the UI. You will need a private property and you cannot notify from a auto-property.

Simple Example:

public class Sample : INotifyPropertyChanged
{
    private string _str;
    public string Str
    {
        get { return _str; }
        set
        {
            _str = value;
            NotifyPropertyChanged(nameof(Str));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanged(string propName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}
Raviraj Palvankar
  • 879
  • 1
  • 5
  • 9
  • 1
    An auto property only works as long as you don't need to be notified about property value changes. Then you would use a property with a backing field, and fire the PropertyChanged event of the INotifyPropertyChanged interface in the property setter. – Clemens Jun 12 '18 at 07:23
  • 1
    This works, but preferably the DataContext should be a ViewModel. You might get som inspiration here: https://stackoverflow.com/questions/46931212/proper-way-of-implementing-mvvm-pattern-in-wpf – Fredrik Claesson Jun 12 '18 at 07:34
  • How do I also get it to work twoway? I mean, when I change the `string` object it should change the `Textbox's` text I tried setting the `Mode=TwoWay` – hebele Jun 12 '18 at 07:52
  • You will have to implement the INotifyPropertyChanged interface for the MainWindow class and call the event handler with the property name "str". Search for notify property changed wpf and you will get the code. – Raviraj Palvankar Jun 12 '18 at 07:54
0

First, data bindings in WPF only work with public properties. So you must explicitely declare one in your code behind (instead of string str;)

public string str { get; set; }

Second, the DataContext property of a view defines the object / class in which the property will be searched for the bindings. The line this.DataContext = str; in your example means that you want your bindings in the view to be looked for inside the str object (which is a string). You should replace this line by

this.DataContext = this;

so that the bindings will be searched inside the code behind of this view itself.

Remark You could also stay with the line this.DataContext = str; if str is a public property and bind using an expression such as

<TextBox Text="{Binding .}" />

which will bind to the value of the DataContext property.

computoms
  • 46
  • 1
  • 5
0

Maybe you can use MVVM light to do the binding.

Dean
  • 24
  • 2