2010-05-06 33 views
6

Tôi đang cố gắng viết một điều khiển người dùng có một ItemsControl, các ItemsTemplate trong đó có một TextBox sẽ cho phép ràng buộc TwoWay. Tuy nhiên, tôi phải làm một sai lầm một nơi nào đó trong mã của tôi, bởi vì các ràng buộc chỉ xuất hiện để làm việc như thể Mode = OneWay. Đây là một đoạn trích khá đơn giản từ dự án của tôi, nhưng nó vẫn chứa các vấn đề:HaiWay ràng buộc với các mụcControl

<UserControl x:Class="ItemsControlTest.UserControl1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Height="300" Width="300"> 
    <Grid> 
     <StackPanel> 
      <ItemsControl ItemsSource="{Binding Path=.}" 
          x:Name="myItemsControl"> 
       <ItemsControl.ItemTemplate> 
        <DataTemplate> 
         <TextBox Text="{Binding Mode=TwoWay, 
               UpdateSourceTrigger=LostFocus, 
               Path=.}" /> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ItemsControl> 
      <Button Click="Button_Click" 
        Content="Click Here To Change Focus From ItemsControl" /> 
     </StackPanel> 
    </Grid> 
</UserControl> 

Dưới đây là đoạn code sau cho sự kiểm soát trên:

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Collections.ObjectModel; 

namespace ItemsControlTest 
{ 
    /// <summary> 
    /// Interaction logic for UserControl1.xaml 
    /// </summary> 
    public partial class UserControl1 : UserControl 
    { 
     public ObservableCollection<string> MyCollection 
     { 
      get { return (ObservableCollection<string>)GetValue(MyCollectionProperty); } 
      set { SetValue(MyCollectionProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for MyCollection. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty MyCollectionProperty = 
      DependencyProperty.Register("MyCollection", 
             typeof(ObservableCollection<string>), 
             typeof(UserControl1), 
             new UIPropertyMetadata(new ObservableCollection<string>())); 

     public UserControl1() 
     { 
      for (int i = 0; i < 6; i++) 
       MyCollection.Add("String " + i.ToString()); 

      InitializeComponent(); 

      myItemsControl.DataContext = this.MyCollection; 
     } 

     private void Button_Click(object sender, RoutedEventArgs e) 
     { 
      // Insert a string after the third element of MyCollection 
      MyCollection.Insert(3, "Inserted Item"); 

      // Display contents of MyCollection in a MessageBox 
      string str = ""; 
      foreach (string s in MyCollection) 
       str += s + Environment.NewLine; 
      MessageBox.Show(str); 
     } 
    } 
} 

Và cuối cùng, đây là XAML cho cửa sổ chính :

<Window x:Class="ItemsControlTest.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:src="clr-namespace:ItemsControlTest" 
     Title="Window1" Height="300" Width="300"> 
    <Grid> 
     <src:UserControl1 /> 
    </Grid> 
</Window> 

Vâng, đó là tất cả. Tôi không chắc chắn lý do tại sao chỉnh sửa các thuộc tính TextBox.Text trong cửa sổ dường như không cập nhật các tài sản nguồn cho các ràng buộc trong mã phía sau, cụ thể là MyCollection. Nhấp vào nút khá nhiều gây ra vấn đề để nhìn chằm chằm vào mặt tôi;) Xin hãy giúp tôi hiểu nơi tôi đang đi sai.

Thanx!

Andrew

Trả lời

7

Ok Tôi tin rằng những gì đang gây ra vấn đề này là bạn đang liên kết trực tiếp đến một String. Các chuỗi là không thay đổi trong C# và do đó khi bạn thay đổi văn bản, nó không thể thay đổi chuỗi cơ bản trong ObservableCollection. Những gì bạn có thể làm để giải quyết vấn đề này đơn giản là tạo ra một lớp mô hình để giữ dữ liệu chuỗi, và sau đó ràng buộc các TextBox.Text vào một thuộc tính bên trong lớp đó. Dưới đây là ví dụ:

public partial class BindingToString : Window 
{ 
    public BindingToString() 
    { 
     MyCollection = new ObservableCollection<TestItem>(); 

     for (int i = 0; i < 6; i++) 
      MyCollection.Add(new TestItem("String " + i.ToString())); 

     InitializeComponent(); 

     myItemsControl.DataContext = this.MyCollection; 
    } 

    public ObservableCollection<TestItem> MyCollection 
    { 
     get; 
     set; 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     // Display contents of MyCollection in a MessageBox 
     string str = ""; 
     foreach (TestItem s in MyCollection) 
      str += s.Name + Environment.NewLine; 
     MessageBox.Show(str); 
    } 
} 

public class TestItem 
{ 
    public string Name 
    { 
     get; 
     set; 
    } 

    public TestItem(string name) 
    { 
     Name = name; 
    } 
} 

Lưu ý rằng tôi đã thay đổi thuộc tính phụ thuộc thành thuộc tính chuẩn - không có lý do gì để thu thập thuộc tính phụ thuộc. Bên cạnh đó sự khác biệt duy nhất là sự bao gồm của lớp wrapper TestItem để giữ dữ liệu chuỗi.

<Window x:Class="TestWpfApplication.BindingToString" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="BindingToString " Height="300" Width="300"> 
<Grid> 
    <StackPanel> 
     <ItemsControl ItemsSource="{Binding}" 
         x:Name="myItemsControl"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <TextBox Text="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
     <Button Click="Button_Click" 
       Content="Click Here To Change Focus From ItemsControl" /> 
    </StackPanel> 
</Grid> 

Bây giờ TextBox được ràng buộc với con đường Name trên TestItem, và các công trình liên kết này và sửa đổi các bộ sưu tập như mong đợi.

+0

Charlie tuyệt vời, có vẻ như bạn đã đóng đinh nó. Bạn đang đề xuất hoạt động tốt! – Andrew

Các vấn đề liên quan