How to get text box to update using WPF Databinding

John Sparks 111 Reputation points
2023-12-18T19:38:41.1566667+00:00

Hi, I am trying to get databinding working using a WPF window for a simple Object stored as a property of the Window's Class.

I have a Class called Car with a Property called Make (i.e. VW, Audi etc).

	public class Car : INotifyPropertyChanged
	{
		public event PropertyChangedEventHandler PropertyChanged;

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

		private string _make;
		public string Make
		{
			get => _make;
			set
			{
				_make = value;
				OnPropertyChanged();
			}
		}
		public Car()
		{ Make = "Empty";}
	}

In the XAML of the WPF form I have a Text box set to bind to Make

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

In the Codebehind of the WPF form the windows constructor and the Car Property is

public WindowCarDetails()
{
// instantiate the private property that contains the class.
//  An empty car has "Empty" as its make
_car = new Car();
InitializeComponent();
this.DataContext = _car;
}

private Car _car;
public Car Car
{
get => _car;
set
	{
	_car = value;
	}
}


In a previous window, I instantiate the Window and pass a car to the Car Property of the Window. I have checked and this does pass over the Car details successfully

WindowCarDetails CarDetails = new();
CarDetails.Car = (Car)CarDataGrid.CurrentItem ;


When I test this, I find that the text field does have "Empty" as its value, so its picking up the default value of the empty Car instance I create. However, it should show the Make of the Car being passed to the Window.

I have tried removing the _car=New Car(); line and then the text box is just blank.

Can someone show me where I am going wrong?

Thanks!

Developer technologies Windows Presentation Foundation
Developer technologies C#
{count} votes

Accepted answer
  1. Viorel 122.5K Reputation points
    2023-12-18T20:38:17.31+00:00

    Try to execute this.DataContext = value inside the set function of WindowCarDetails.

    1 person found this answer helpful.

2 additional answers

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,341 Reputation points
    2023-12-18T20:52:27.1166667+00:00

    Hi,
    <TextBox Text="{Binding Make}"/>

    • text is binded to property "Make" in DataContext.

    _car = new Car();
    this.DataContext = _car;

    • in this case DataContext is an instance of class Car with property "Make".

    If you want bind Car property of Window class you must set DataContext to Window instance (this) and bind text to "Car.Make".

    this.Car = new Car(); 
    InitializeComponent(); 
    this.DataContext = this;
    
    
    <TextBox Text="{Binding Car.Make}"/>
    

    Another approach is to use additional level with separate DataContext:

    			_car = new Car();
    			InitializeComponent();
    			this.DataContext = this;
    
        <Grid DataContext="{Binding Car}">
          <TextBox Text="{Binding Make}"/>
        </Grid>
    
    1 person found this answer helpful.

  2. Peter Fleischer (former MVP) 19,341 Reputation points
    2023-12-19T18:11:52.2866667+00:00

    Hi John,
    try following demo:

    XAML:

    <Window x:Class="WpfApp125.Window125"
            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:WpfApp125"
            mc:Ignorable="d"
            Title="John Sparks_231218" Height="300" Width="300">
      <Window.DataContext>
        <local:ViewModel/>
      </Window.DataContext>
      <Grid>
        <Grid.ColumnDefinitions>
          <ColumnDefinition/>
          <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <DataGrid ItemsSource="{Binding CarList}" SelectedItem="{Binding Car}"/>
        <Grid Grid.Column="1" DataContext="{Binding Car}">
          <TextBox Text="{Binding Make}"/>
        </Grid>
      </Grid>
    </Window>
    

    Code:

    using System;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    
    namespace WpfApp125
    {
    	/// <summary>
    	/// Interaction logic for Window125.xaml
    	/// </summary>
    	public partial class Window125 : Window
    	{
    		public Window125()
    		{
    			InitializeComponent();
    		}
    	}
    
    	public class ViewModel : INotifyPropertyChanged
    	{
    		public event PropertyChangedEventHandler PropertyChanged;
    
    		private void OnPropertyChanged([CallerMemberName] String propertyName = "")
    		{
    			PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    		}
    
    		// contructor: load CarList 
    		public ViewModel() { for (int i = 1; i <= 10; i++) CarList.Add(new Car() { Make = $"Car {i}" }); }
    
    		public ObservableCollection<Car> CarList { get; set; } = new ObservableCollection<Car>();
    
    
    		private Car _car;
    		public Car Car
    		{
    			get => _car;
    			set
    			{
    				_car = value;
    				OnPropertyChanged();
    			}
    		}
    	}
    
    
    	public class Car : INotifyPropertyChanged
    	{
    		public event PropertyChangedEventHandler PropertyChanged;
    
    		private void OnPropertyChanged([CallerMemberName] String propertyName = "")
    		{
    			PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    		}
    
    		private string _make;
    		public string Make
    		{
    			get => _make;
    			set
    			{
    				_make = value;
    				OnPropertyChanged();
    			}
    		}
    		public Car()
    		{ Make = "Empty"; }
    	}
    }
    
    

    Result:

    x

    1 person found this answer helpful.

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.