silverlight:ListBox中如何取得DateTemplate/ItemsPanelTemplate中的命名控件?

Xaml如下:
代码
<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>

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;}}
}

这里我们借助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>

如果想在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了

posted @ 2010-01-03 14:03  菩提树下的杨过  阅读(3284)  评论(2编辑  收藏  举报