代码
<UserControl x:Class="ToolsTest.Test"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<UserControl.Resources>
<DataTemplate x:Key="dt">
<TextBlock Padding="5,0,5,0" Text="{Binding d}" x:Name="myTxt"/>
</DataTemplate>
</UserControl.Resources>
<StackPanel>
<ListBox Name="myListBox" ItemTemplate="{StaticResource dt}" />
<Button Content="查找myTxt" x:Name="btnFind" Width="90" Click="btnFind_Click"></Button>
</StackPanel>
</UserControl>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<UserControl.Resources>
<DataTemplate x:Key="dt">
<TextBlock Padding="5,0,5,0" Text="{Binding d}" x:Name="myTxt"/>
</DataTemplate>
</UserControl.Resources>
<StackPanel>
<ListBox Name="myListBox" ItemTemplate="{StaticResource dt}" />
<Button Content="查找myTxt" x:Name="btnFind" Width="90" Click="btnFind_Click"></Button>
</StackPanel>
</UserControl>
Xaml.cs如下:
代码
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ToolsTest
{
public partial class Test : UserControl
{
ObservableCollection<TestData> oc;
public Test()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Test_Loaded);
}
void Test_Loaded(object sender, RoutedEventArgs e)
{
oc = new ObservableCollection<TestData>();
oc.Add(new TestData() { d = "A" });
oc.Add(new TestData() { d = "B" });
this.myListBox.ItemsSource = oc;
}
private void btnFind_Click(object sender, RoutedEventArgs e)
{
if (myListBox.SelectedItem != null)
{
ListBoxItem _selectedItem = (ListBoxItem)(myListBox.ItemContainerGenerator.ContainerFromItem(myListBox.SelectedItem));
TextBlock myTxt = FindFirstVisualChild<TextBlock>(_selectedItem, "myTxt");
MessageBox.Show(string.Format("选中行的TextBlock值为:" + myTxt.Text));
}
ListBoxItem _firstItem = (ListBoxItem)(myListBox.ItemContainerGenerator.ContainerFromItem(myListBox.Items[0]));
//var t = _firstItem.FindName("myTxt");//这样是找不到的
TextBlock myTxtFirst = FindFirstVisualChild<TextBlock>(_firstItem, "myTxt");
MessageBox.Show(string.Format("第一行的TextBlock值为:" + myTxtFirst.Text));
}
public T FindFirstVisualChild<T>(DependencyObject obj,string childName) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T && child.GetValue(NameProperty).ToString()==childName)
{
return (T)child;
}
else
{
T childOfChild = FindFirstVisualChild<T>(child,childName);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return null;
}
}
public class TestData{public string d{set;get;}}
}
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace ToolsTest
{
public partial class Test : UserControl
{
ObservableCollection<TestData> oc;
public Test()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Test_Loaded);
}
void Test_Loaded(object sender, RoutedEventArgs e)
{
oc = new ObservableCollection<TestData>();
oc.Add(new TestData() { d = "A" });
oc.Add(new TestData() { d = "B" });
this.myListBox.ItemsSource = oc;
}
private void btnFind_Click(object sender, RoutedEventArgs e)
{
if (myListBox.SelectedItem != null)
{
ListBoxItem _selectedItem = (ListBoxItem)(myListBox.ItemContainerGenerator.ContainerFromItem(myListBox.SelectedItem));
TextBlock myTxt = FindFirstVisualChild<TextBlock>(_selectedItem, "myTxt");
MessageBox.Show(string.Format("选中行的TextBlock值为:" + myTxt.Text));
}
ListBoxItem _firstItem = (ListBoxItem)(myListBox.ItemContainerGenerator.ContainerFromItem(myListBox.Items[0]));
//var t = _firstItem.FindName("myTxt");//这样是找不到的
TextBlock myTxtFirst = FindFirstVisualChild<TextBlock>(_firstItem, "myTxt");
MessageBox.Show(string.Format("第一行的TextBlock值为:" + myTxtFirst.Text));
}
public T FindFirstVisualChild<T>(DependencyObject obj,string childName) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T && child.GetValue(NameProperty).ToString()==childName)
{
return (T)child;
}
else
{
T childOfChild = FindFirstVisualChild<T>(child,childName);
if (childOfChild != null)
{
return childOfChild;
}
}
}
return null;
}
}
public class TestData{public string d{set;get;}}
}
这里我们借助VisualTreeHelper对指定行(ListBoxItem)做了一个遍历,以查找符合要求的控件
对于ItemsPanelTemplate中的命名控件,比如下面这样的:
代码
<ListBox>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" x:Name="sp"></StackPanel>
</ItemsPanelTemplate>
<ListBox.ItemTemplate>
<DataTemplate>
<Rectangle Width="100" Height="100" Fill="{Binding Color}" x:Name="listItem" MouseLeftButtonDown="listItem_MouseLeftButtonDown"></Rectangle>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" x:Name="sp"></StackPanel>
</ItemsPanelTemplate>
<ListBox.ItemTemplate>
<DataTemplate>
<Rectangle Width="100" Height="100" Fill="{Binding Color}" x:Name="listItem" MouseLeftButtonDown="listItem_MouseLeftButtonDown"></Rectangle>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
如果想在listItem_MouseLeftButtonDown中引用sp,按正统处理方法还真是比较麻烦(各位可以google,baidu印证),这里给出一个很取巧的办法:
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" x:Name="sp" Loaded="sp_Loaded"></StackPanel>
</ItemsPanelTemplate>
然后在后端代码中,添加一个私有变量,并处理sp_Loaded事件:
StackPanel _sp = null;
private void sp_Loaded(object sender, RoutedEventArgs e)
{
_sp = sender as StackPanel;
}
这样,在listItem_MouseLeftButtonDown中就能借助"_sp"正确引用到ItemsPanelTemplate中的sp了