2010-03-20 84 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(); 
} 
相關問題