I am trying to bind an observable collection to a user control but it is not getting updated on user change but it is getting updated when the user control is changed through code. Following is an example i tried. It might be a bit long but it is working so you can copy and paste the code as it is.
Please see my question at the end of the post.
--Customer.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel; namespace TestMVVM { class Customer : INotifyPropertyChanged { private string firstName; private string lastName; public string FirstName { get { return firstName; } set { if (firstName != value) { firstName = value; RaisePropertyChanged("FirstName"); } } } public string LastName { get { return lastName; } set { if (lastName != value) { lastName = value; RaisePropertyChanged("LastName"); } } } #region PropertChanged Block public event PropertyChangedEventHandler PropertyChanged; private void RaisePropertyChanged(string property) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(property)); } } #endregion } }
--UCTextBox.xaml
<UserControl x:Class="TestMVVM.UCTextBox"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Height="40" Width="200">
<Grid>
<TextBox Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="txtTextControl"
VerticalAlignment="Top" Width="120" />
</Grid>
--UCTextBox.xaml.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Collections.ObjectModel; using System.ComponentModel; namespace TestMVVM { /// /// Interaction logic for UCTextBox.xaml /// public partial class UCTextBox : UserControl, INotifyPropertyChanged { public UCTextBox() { InitializeComponent(); } public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(UCTextBox), new UIPropertyMetadata(string.Empty, new PropertyChangedCallback(textChangedCallBack))); static void textChangedCallBack(DependencyObject property, DependencyPropertyChangedEventArgs args) { UCTextBox pasTextBox = (UCTextBox)property; pasTextBox.txtTextControl.Text = (string)args.NewValue; } public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); NotifyPropertyChanged("Text"); } } private void NotifyPropertyChanged(String info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion } }
-- Window1.xaml
<Window x:Class="TestMVVM.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestMVVM"
Title="Window1" Height="300" Width="300">
<Grid>
<local:UCTextBox x:Name="txtUC" />
<Button Height="23" HorizontalAlignment="Left" Margin="39,0,0,82"
Name="btnUpdate" VerticalAlignment="Bottom" Width="75" Click="btnUpdate_Click">Update</Button>
<Button Height="23" Margin="120,0,83,82" Name="btnChange" VerticalAlignment="Bottom" Click="btnChange_Click">Change</Button>
</Grid>
-- Window1.xaml.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Collections.ObjectModel; namespace TestMVVM { /// /// Interaction logic for Window1.xaml /// public partial class Window1 : Window { CustomerHeaderViewModel customerHeaderViewModel = null; public Window1() { InitializeComponent(); customerHeaderViewModel = new CustomerHeaderViewModel(); customerHeaderViewModel.LoadCustomers(); txtUC.DataContext = customerHeaderViewModel.Customers[0]; Binding binding = new Binding(); binding.Source = customerHeaderViewModel.Customers[0]; binding.Path = new System.Windows.PropertyPath("FirstName"); binding.Mode = BindingMode.TwoWay; binding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged; txtUC.SetBinding(UCTextBox.TextProperty, binding); } private void btnUpdate_Click(object sender, RoutedEventArgs e) { MessageBox.Show(customerHeaderViewModel.Customers[0].FirstName); } private void btnChange_Click(object sender, RoutedEventArgs e) { txtUC.Text = "Tom"; } } class CustomerHeaderViewModel { public ObservableCollection Customers { get; set; } public void LoadCustomers() { ObservableCollection customers = new ObservableCollection(); customers.Add(new Customer { FirstName = "Jim", LastName = "Smith", NumberOfContracts = 23 }); Customers = customers; } } }
When i run the Window1.xaml my user control shows the data as "Jim". Now when i change the text to say "John" and click on Update, the messagebox still shows "Jim" that means the observable collection is not getting updated. When i click on Change button the user control changes the data to "Tom". Now when i click on Update button the Messagebox shows "Tom". Can anyone please tell me how to achieve the updation of observable collection by changing the data in user control rather than through code?