2010-03-20 92 views
0

我有一些XAML如何确定项目是否是WPF ItemTemplate中的最后一个项目?

<ItemsControl Name="mItemsControl"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate> 
      <TextBox Text="{Binding Mode=OneWay}" KeyUp="TextBox_KeyUp"/> 
     </DataTemplate> 
    </ItemsControl.ItemTemplate> 
</ItemsControl> 

一个绑定到一个简单的ObservableCollection

private ObservableCollection<string> mCollection = new ObservableCollection<string>(); 

public MainWindow() 
{ 
    InitializeComponent(); 

    this.mCollection.Add("Test1"); 
    this.mCollection.Add("Test2"); 
    this.mItemsControl.ItemsSource = this.mCollection; 
} 

击中后在最后文本框回车键,我想另一个文本框出现。我有一些代码做的,但有一个缺口:

private void TextBox_KeyUp(object sender, KeyEventArgs e) 
{ 
    if (e.Key != Key.Enter) 
    { 
     return; 
    } 

    TextBox textbox = (TextBox)sender; 

    if (IsTextBoxTheLastOneInTheTemplate(textbox)) 
    { 
     this.mCollection.Add("A new textbox appears!"); 
    } 
} 

功能IsTextBoxTheLastOneInTheTemplate()是,我需要的东西,但无法弄清楚如何写。我怎么去写它?

我已经考虑过使用ItemsControl.ItemContainerGenerator,但不能把所有的东西放在一起。

谢谢!

-Mike

回答

0

我能够参照http://drwpf.com/blog/2008/07/20/itemscontrol-g-is-for-generator/得到一个体面的解决办法。不是超级优雅,但它为我工作。

private void TextBox_KeyUp(object sender, KeyEventArgs e) 
    { 
     if (e.Key != Key.Enter) 
     { 
      return; 
     } 

     TextBox textbox = (TextBox)sender; 

     var lastContainer = this.mItemsControl.ItemContainerGenerator.ContainerFromIndex(this.mItemsControl.Items.Count - 1); 

     var visualContainer = (Visual)lastContainer; 

     var containedTextbox = (TextBox)GetDescendantByType(visualContainer, typeof(TextBox)); 

     var isSame = textbox == containedTextbox; 

     if (isSame) 
     { 
      this.mCollection.Add("A new textbox appears!"); 
     } 
    } 


    public static Visual GetDescendantByType(Visual element, Type type) 
    { 
     if (element.GetType() == type) return element; 

     Visual foundElement = null; 

     if (element is FrameworkElement) 
      (element as FrameworkElement).ApplyTemplate(); 

     for (int i = 0; 
      i < VisualTreeHelper.GetChildrenCount(element); i++) 
     { 
      Visual visual = VisualTreeHelper.GetChild(element, i) as Visual; 
      foundElement = GetDescendantByType(visual, type); 
      if (foundElement != null) 
       break; 
     } 

     return foundElement; 
    } 
0

我假设这是你工作的简化版本。单向绑定到字符串集合的文本框对我来说没有意义。

在这种情况下的主要问题是使用一个简单的字符串作为项目源。我假设我们不能保证字符串是唯一的,所以我们不能从textbox.Text得出任何结论。另外,由于字符串是不可变的,我们不能使用字符串的实例来推断任何东西。

解决方案的第一步是创建一个类来容纳我们可以引用的数据。 (这似乎在这种情况下,一个有点傻,因为它只是拥有一个字符串。)

class MyData 
    { 
     public string Value { get; set; } 
    } 

你的第二个代码块变为:

ObservableCollection<MyData> mCollection = new ObservableCollection<MyData>(); 

    public MainWindow() 
    { 
     InitializeComponent(); 

     this.mCollection.Add(new MyData { Value = "Test1" }); 
     this.mCollection.Add(new MyData { Value = "Test2" }); 
     this.mItemsControl.ItemsSource = this.mCollection; 
    } 

我们将使用文本框的标签属性来存储一个参考我们的绑定来源。我们将用它来解决唯一性问题。在XAML变为:

<ItemsControl Name="mItemsControl"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <TextBox Text="{Binding Value}" Tag="{Binding}" KeyUp="TextBox_KeyUp"/> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 

最后,处理程序变为:

private void TextBox_KeyUp(object sender, KeyEventArgs e) 
    { 
     if (e.Key != Key.Enter) 
     { 
      return; 
     } 

     TextBox textbox = (TextBox)sender; 

     if (mItemsControl.Items.IndexOf(textbox.Tag) == mItemsControl.Items.Count - 1) 
     { 
      this.mCollection.Add(new MyData() { Value = "A new textbox appears!" }); 
     } 
    } 
0

在我看来,这是在视图模型最好的定义的行为:

public class ItemCollection : ObservableCollection<Item> 
{ 
    public ItemCollection() 
    { 
     // this guarantees that any instance created always has at least one 
     // item in it - you don't need this if you're creating instances in 
     // code, but if you just create them in XAML you do. 
     Item item = new Item(this); 
     Add(item); 
    } 
} 

public class Item 
{ 
    internal Item(ItemCollection owner) 
    { 
     Owner = owner; 
    } 

    public bool IsLast 
    { 
     get 
     { 
      return Owner.LastOrDefault() == this; 
     } 
    } 

    private ItemCollection Owner { get; set; } 

    private string _Value; 

    // here's the actual behavior: if the last item in the collection is 
    // given a non-empty Value, a new item gets added after it. 
    public string Value 
    { 
     get { return _Value; } 
     set 
     { 
      _Value = value; 
      if (IsLast && !String.IsNullOrEmpty(_Value)) 
      { 
       Owner.Add(new Item(Owner)); 
      } 
     } 
    } 
} 

从这里,它使得TextBox更新其来源的一个简单的事情,当用户按下ENTER键:

<DataTemplate DataType="{x:Type local:Item}"> 
    <TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=Explicit}" 
      KeyUp="TextBox_KeyUp"/> 
</DataTemplate> 

随着KeyUp事件处理程序:

private void TextBox_KeyUp(object sender, KeyEventArgs e) 
{ 
    if (e.Key != Key.Enter) 
    { 
     return; 
    } 

    TextBox t = (TextBox)sender; 
    BindingExpression be = t.GetBindingExpression(TextBox.TextProperty); 
    be.UpdateSource(); 
} 
相关问题