.net 如何确定项目是否是WPF ItemTemplate中的最后一个项目?
我有一些XAML.net 如何确定项目是否是WPF ItemTemplate中的最后一个项目?,.net,wpf,data-binding,itemtemplate,.net,Wpf,Data Binding,Itemtemplate,我有一些XAML <ItemsControl Name="mItemsControl"> <ItemsControl.ItemTemplate> <DataTemplate> <TextBox Text="{Binding Mode=OneWay}" KeyUp="TextBox_KeyUp"/> </DataTemplate> </ItemsControl.
<ItemsControl Name="mItemsControl">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Mode=OneWay}" KeyUp="TextBox_KeyUp"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
我需要ISTExtBoxTheLastNeintheTemplate函数,但不知道如何编写。我该怎么写呢
我曾考虑过使用ItemsControl.ItemContainerGenerator,但无法将所有部分放在一起
谢谢
-迈克我假设这是你正在研究的东西的简化版本。一个单向绑定到字符串集合的文本框对我来说没有意义 本例中的主要问题是使用简单字符串作为项源。我假设我们不能保证字符串是唯一的,所以我们不能从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;
}
通过引用,我得到了一个不错的解决方案。不是很优雅,但对我来说很管用
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;
}
在我看来,这是视图模型中最好定义的行为:
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));
}
}
}
}
使用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();
}
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!" });
}
}
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;
}
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));
}
}
}
}
<DataTemplate DataType="{x:Type local:Item}">
<TextBox Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=Explicit}"
KeyUp="TextBox_KeyUp"/>
</DataTemplate>
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();
}