I have some XAML:
<ItemsControl Name="mItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Mode=OneWay}" KeyUp="TextBox_KeyUp"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
that's bound to a simple ObservableCollection
private ObservableCollection<string> mCollection = new ObservableCollection<string>();
public MainWindow()
{
InitializeComponent();
this.mCollection.Add("Test1");
this.mCollection.Add("Test2");
this.mItemsControl.ItemsSource = this.mCollection;
}
Upon hitting the enter key in the last TextBox, I want another TextBox to appear. I have code that does it, but there's a gap:
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!");
}
}
The function IsTextBoxTheLastOneInTheTemplate() is something that I need, but can't figure out how to write. How would I go about writing it?
I've considered using ItemsControl.ItemContainerGenerator, but can't put all the pieces together.
I was able to get a decent solution by referring to http://drwpf.com/blog/2008/07/20/itemscontrol-g-is-for-generator/. Not super-elegant, but it worked for me.
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;
}