2010-08-19 149 views
2

我想綁定一個可觀察集合到用戶控件,但它沒有得到更新用戶更改,但它更新時通過代碼更改用戶控件。以下是我嘗試的一個例子。它可能有點長,但它正在工作,所以你可以複製和粘貼代碼。可觀察的集合沒有得到更新UI更改

請在帖子末尾查看我的問題。

--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 
    } 
} 

- 窗口1。 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; 
     } 
    } 
} 

當我運行Window1.xaml我的用戶控件顯示的數據爲 「吉姆」。現在,當我改變文本說「約翰」,點擊更新,消息框仍然顯示「吉姆」,這意味着可觀察集合沒有得到更新。當我點擊更改按鈕時,用戶控件將數據更改爲「湯姆」。現在當我點擊更新按鈕時,Messagebox顯示「Tom」。任何人都可以告訴我如何通過更改用戶控件中的數據而不是通過代碼來實現可觀察集合的更新?

回答

2

這是因爲您沒有處理txtTextControl.TextChanged事件,所以您的Text依賴項屬性從不更新。

無論如何,你不必是一個DependencyPropertyChangedCallback和事件處理程序手動處理,你可以綁定txtTextControl.TextText依賴屬性:

<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}}}"/> 
+0

IT WORKED .. !!!!夢幻托馬斯.. !!!上帝,我一整天都在做這件事。太好了..只需要改變一下Text binding,你可以在你的答案中改變它,以便其他人可以使用它,也就是說,Mode = TwoWay缺失,這給了我一個構建錯誤,例如 Text =「{ Binding Path = Text,Mode = TwoWay,RelativeSource = {RelativeSource Mode = FindAncestor, AncestorType = {x:Type local:UCTextBox}}}「 – samar 2010-08-19 13:13:19

+0

TextBox.Text默認爲雙向綁定,因此您不必製作它明確。無論如何,它不應該給你一個構建錯誤...這很奇怪 – 2010-08-19 13:20:51

+0

哦,是這樣.. !!!但是,它確實給了我一個構建錯誤。 – samar 2010-08-20 05:55:39

0

可觀察集合,觀察員集合只。當單個項目的字段確實發生變化時,您將收到有關添加或刪除項目的通知。這是完全不同的東西。就像Thomas Levesque說的那樣,你只需要綁定正確的屬性。

相關問題