WPF XAML binding does not update
it should be something like this to work,
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBlock x:Name="First" Text="{Binding FirstString}" Grid.Row="0"/>
<TextBlock x:Name="Second" Text="{Binding SecondString}" Grid.Row="1"/>
<TextBlock x:Name="Third" Text="{Binding ThirdString}" Grid.Row="2"/>
<TextBlock x:Name="Fourth" Text="{Binding FourthString}" Grid.Row="3"/>
</Grid>
and c# code will be like,
public string FirstString { get; set; }
public string SecondString { get; set; }
public string ThirdString { get; set; }
public string FourthString { get; set; }
public MainWindow()
{
InitializeComponent();
FirstString = "First";
SecondString = "Second";
ThirdString = "Third";
FourthString= "Fourth";
this.DataContext = this; //here you set the context to current instance of window
}
There are a few things that are incorrect. The Binding
markup will look at the object in the DataContext
property of the control. This property inherits the DataContext
from the declaring parent unless otherwise specified. Out of the box, this is null
for a Window
control.
There are two options for this problem. You can either set the DataContext
explicitely in the code-behind or the XAML
// In XAML
<Window DataContext={Binding RelativeSource={RelativeSource Self}}>
or
// In the code-behind
DataContext = this;
Another problem is that the binding is applied at initialization. Initially, your properties are empty. After the InitializeComponent
phase, the controls will "bind" to the properties (which are empty). When you set your properties afterward, the controls have no way to know it has changed. There are two mechanism to allow this. On the control level, you can make these properties as DependencyProperty
or implement the INotifyPropertyChanged
interface and raise the changes. If you want to go the INPC route, you can implement your properties and Window as such:
public partial class MainWindow : INotifyPropertyChanged
{
private string firstString;
private string secondString;
private string thirdString;
private string fourthString;
public string FirstString
{
get { return firstString; }
set
{
firstString = value;
RaisePropertyChanged("FirstString");
}
}
public string SecondString
{
get { return secondString; }
set
{
secondString = value;
RaisePropertyChanged("SecondString");
}
}
public string ThirdString
{
get { return thirdString; }
set
{
thirdString = value;
RaisePropertyChanged("ThirdString");
}
}
public string FourthString
{
get { return fourthString; }
set
{
fourthString = value;
RaisePropertyChanged("FourthString");
}
}
public MainWindow()
{
DataContext = this;
InitializeComponent();
FirstString = "First";
SecondString = "Second";
ThirdString = "Third";
FourthString = "Fourth";
}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
private void RaisePropertyChanged(string propertyName)
{
var handlers = PropertyChanged;
handlers(this, new PropertyChangedEventArgs(propertyName));
}
}
Unless specified otherwise, the path of the binding is relative to the DataContext
of the element. In your case, I suspect you didn't specify a DataContext
at all...
Since the properties are declared in the MainWindow
class itself, the easiest fix is to add:
DataContext = this;
at the end of the constructor.