2010-05-06 4 views
6

ItemsControl이있는 사용자 정의 컨트롤을 작성하려고하는데, 그 중 ItemsTemplate에는 TwoWay 바인딩을 허용하는 TextBox가 들어 있습니다. 그러나 바인딩은 Mode = OneWay처럼 작동하는 것처럼 보이기 때문에 필자는 코드 내에서 어딘가에서 실수를해야합니다. 이것은 내 프로젝트에서 꽤 간단한 발췌 한 것입니다,하지만 여전히 문제가 포함되어 여기 TwoWay With ItemsControl

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

위의 컨트롤에 대한 코드 뒤에 :

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

마지막을 여기에 메인 창에 대한 XAML의 :

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

글쎄, 그게 전부입니다. 왜 Window에서 TextBox.Text 속성을 편집해도 MyCollection의 코드에서 바인딩의 소스 속성을 업데이트하지 않는 것 같습니다. 버튼을 클릭하면 문제가 나를 얼굴로 쳐다 보게됩니다.) 제가 잘못되어 가고있는 부분을 이해하도록 도와주세요.

고맙습니다.

앤드류

답변

7

가 좋아 나는이 문제를 당신이 String에 직접 결합되어있다 원인을 생각합니다. 문자열은 이며 C#에서는으로 변경할 수 없으므로 텍스트를 변경하면 ObservableCollection에있는 기본 문자열을 변경할 수 없습니다. 이 문제를 해결하기 위해 할 수있는 일은 단순히 문자열 데이터를 보유 할 모델 클래스를 만든 다음 TextBox.Text을 해당 클래스의 속성에 바인딩합니다. 내가 수집 종속성 속성 수 있도록 할 이유가없는 표준 속성 인에 종속성 속성을 변경

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

공지 예를 ​​들면 다음과 같습니다. 그 외의 유일한 차이점은 래퍼 클래스 TestItem을 포함하여 문자열 데이터를 포함한다는 것입니다. 예상대로 이제 TextBoxTestItemName 경로에 바인딩

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

,이 바인딩 작품과 컬렉션을 수정합니다.

+0

멋진 찰리예요. 너는 제안이 잘 작동한다! – Andrew