How can I bind a custom object in code-behind to a Grid in XAML?
In the following example, the Message property binds correctly but the FirstName, LastName and Age properties of the Customer object are blank. Why is that?
XAML:
<Window x:Class="TestBinding9922.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
<TextBlock Text="{Binding Message}"/>
<Grid DataContext="{Binding Customer}" >
<Grid.RowDefi开发者_运维技巧nitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Content="First Name:" />
<Label Grid.Column="0" Grid.Row="1" Content="Last Name:" />
<Label Grid.Column="0" Grid.Row="2" Content="Age:" />
<TextBox Grid.Column="1" Grid.Row="0" Text="{Binding FirstName}" />
<TextBox Grid.Column="1" Grid.Row="1" Text="{Binding LastName}" />
<TextBox Grid.Column="1" Grid.Row="2" Text="{Binding Age}" />
</Grid>
</StackPanel>
</Window>
Code-Behind:
using System.Windows;
using System.ComponentModel;
namespace TestBinding9922
{
public partial class Window1 : Window, INotifyPropertyChanged
{
public string Message { get; set; }
public Customer Customer { get; set; }
public Window1()
{
InitializeComponent();
DataContext = this;
Message = "this works";
Customer customer = new Customer() { FirstName = "Jim", LastName = "Smith", Age = 45 };
}
}
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
}
Addendum:
Even when I use INotifyPropertyChanged, the textboxes are still blank:
using System.Windows;
using System.ComponentModel;
namespace TestBinding9922
{
public partial class Window1 : Window, INotifyPropertyChanged
{
#region ViewModelProperty: Message
private string _message;
public string Message
{
get
{
return _message;
}
set
{
_message = value;
OnPropertyChanged("Message");
}
}
#endregion
#region ViewModelProperty: Customer
private Customer _customer;
public Customer Customer
{
get
{
return _customer;
}
set
{
_customer = value;
OnPropertyChanged("Customer");
}
}
#endregion
public Window1()
{
InitializeComponent();
DataContext = this;
Message = "this works";
Customer customer = new Customer() { FirstName = "Jim", LastName = "Smith", Age = 45 };
}
#region INotifiedProperty Block
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
public class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
}
Your Customer class needs to implement INotifyPropertyChanged and subsequently the properties that are being changed need to notify when they get changed.
You can find an example of this here, among other places.
Also, you're not instantiating your Customer property, you're creating a local variable; it should be:
Customer = new Customer()
{ FirstName = "Jim", LastName = "Smith", Age = 45 };
It looks like you're assigning the new Customer instance to a local variable "customer" instead of to your Window's property.
You could remove the setting of the DataContext for the grid in the XAML, and then bind the textboxes to Customer.FirstName, etc.
Or, you could remove the setting of the DataContext for the grid in the XAML, as before, but give the grid a name, and then set its DataContext in the code-behind, like you did for the window.
精彩评论