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了

你可能感兴趣的:(silverlight)