observable collection not getting updated on UI change
我试图将一个可观察的集合绑定到一个用户控件,但它不会在用户更改时得到更新,而是在通过代码更改用户控件时得到更新。下面是我尝试的一个例子。它可能有点长,但它在工作,所以您可以复制和粘贴代码。
请在邮件末尾看到我的问题。
客户C.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | 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(UCTExtBox.xaml)
1 2 3 4 5 6 7 8 | <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(扩展文本框.xaml.cs)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | 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 } } |
——Windows 1.xAML
1 2 3 4 5 6 7 8 9 10 11 | <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> |
--窗口1.xaml.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | 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; } } } |
当我运行window1.xaml时,我的用户控件将数据显示为"jim"。现在,当我将文本更改为"john"并单击"更新"时,消息框仍然显示"jim",这意味着可观察的集合没有得到更新。当我单击更改按钮时,用户控件将数据更改为"Tom"。现在,当我单击更新按钮时,消息框显示"汤姆"。有人能告诉我如何通过更改用户控件中的数据而不是通过代码来更新可观察的收集吗?
这是因为您没有处理
无论如何,您不需要使用
1 2 3 | <TextBox Height="23" HorizontalAlignment="Left" Margin="10,10,0,0" Name="txtTextControl" VerticalAlignment="Top" Width="120" Text="{Binding Path=Text, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:UCTextBox}}}"/> |
一个可观察的集合,仅观察该集合。当添加或删除项目时,您将收到通知,而不是当单个项目的字段发生更改时。这完全不同。就像托马斯·列夫斯基说的,你只需要把正确的财产捆绑起来。