MSDN上FindName有这样一句话,如果元素具有子元素,这些子元素都按递归方式搜索请求的命名元素。所以,不管XAML中嵌套了多少层Grid,StackPane之类的,只要知道控件所在的一个容器以及要找的控件Name,就可以用FindName去找到控件,然后去操作。
XAML如下:
<Grid>
<StackPanel Name="stkpanel1">
<StackPanel Name="stkpanel2">
<TextBox Name="txtbox1" Width="50" Height="30" HorizontalAlignment="Left"/>
</StackPanel>
<StackPanel Name="stkpanel3">
<TextBox Name="txtbox2" Width="50" Height="30" HorizontalAlignment="Left"/>
<Button Name="btn" Content="Find" Click="btn1_Click" Height="30" Width="50" HorizontalAlignment="Left"/>
</StackPanel>
</StackPanel>
</Grid>
CS文件中很简单的一段:
private void btn1_Click(object sender, RoutedEventArgs e)
{
TextBox txtbox = (stkpanel1.FindName("txtbox2")) as TextBox;
txtbox.Text = "Gotcha";
}
结果就是这样:
上面是最简单的例子,下面是一个TreeView里面的用法。
<Window.Resources>
<Style TargetType="TreeViewItem">
<Setter Property="IsExpanded" Value="True" />
</Style>
</Window.Resources>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TreeView Name="TVCountry" Margin="3">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<StackPanel Orientation="Horizontal">
<CheckBox Name="chkbox"/>
<TextBlock Name="txtblock" Text="{Binding Name}" MouseLeftButtonDown="txtblock_MouseLeftButtonDown" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
<StackPanel Grid.Column="1">
<TextBox Name="txtbox"/>
</StackPanel>
</Grid>
这个是XAML,最上面的Resources就是初始化的时候把树形控件的节点全部展开,不需要的话删掉就行。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
this.Create();
}
public class TreeNode
{
public string Name { set; get; }
public int ID { set; get; }
public int ParentID { set; get; }
public List<TreeNode> Children { set; get; }
}
//加载数据
void Create()
{
List<TreeNode> listtmp = new List<TreeNode>();
List<TreeNode> list = new List<TreeNode>();
listtmp.Add(new TreeNode() { Name = "中国", ID = 101, ParentID = 0 , Children = new List<TreeNode>() });
listtmp.Add(new TreeNode() { Name = "江苏", ID = 102, ParentID = 101, Children = new List<TreeNode>() });
listtmp.Add(new TreeNode() { Name = "浙江", ID = 103, ParentID = 101, Children = new List<TreeNode>() });
listtmp.Add(new TreeNode() { Name = "南京", ID = 104, ParentID = 102, Children = new List<TreeNode>() });
listtmp.Add(new TreeNode() { Name = "苏州", ID = 105, ParentID = 102, Children = new List<TreeNode>() });
listtmp.Add(new TreeNode() { Name = "温州", ID = 106, ParentID = 103, Children = new List<TreeNode>() });
listtmp.Add(new TreeNode() { Name = "宁波", ID = 107, ParentID = 103, Children = new List<TreeNode>() });
listtmp.Add(new TreeNode() { Name = "美国", ID = 108, ParentID = 0, Children = new List<TreeNode>() });
listtmp.Add(new TreeNode() { Name = "加利福尼亚", ID = 109, ParentID = 108, Children = new List<TreeNode>() });
listtmp.Add(new TreeNode() { Name = "洛杉矶", ID = 110, ParentID = 109, Children = new List<TreeNode>() });
foreach (var item in listtmp)
{
if (item.ParentID == 0)
{
list.Add(item);
}
foreach (var item1 in listtmp)
{
if (item1.ParentID == item.ID)
{
item.Children.Add(item1);
//item.Children = listtmp.Where(v => v != null && v.ParentID != null && v.ParentID == item.ID).ToList();
}
}
}
this.TVCountry.ItemsSource = list;
}
private void txtblock_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
TextBlock tb = sender as TextBlock;
txtbox.Text = tb.Text;
StackPanel stk = (VisualTreeHelper.GetParent(tb)) as StackPanel;
CheckBox chk = (stk.FindName("chkbox")) as CheckBox;
chk.IsChecked = !chk.IsChecked;
}
}
(不知道上面为什么会有 <span style= "white-space:pre" > </span> 删掉就行。)
由于就是一个简单的例子,就直接在代码里给出了数据。
这里需要的效果是点击树形控件TextBlock部分的时候,CheckBox也会相应的变化,在右边的TextBox里显示出TextBlock里的文字。所以就通过TextBlock找到了它的上层容器StackPanel,然后通过FindName找到CheckBox,大功告成。
继续往下写,还可以将这个小程序更加完善一点。
但是这里的问题是,选中TextBlock以后可以改变CheckBox,但是点击CheckBox却不会选中相应的TreeViewItem。没关系,我们再往下加功能。
首先给CheckBox加一个事件,像这样
<CheckBox Name="chkbox" Click="chkbox_Click" />
在上面的CS文件里加上下面一段
private void chkbox_Click(object sender, RoutedEventArgs e)
{
CheckBox chkbox = sender as CheckBox;
StackPanel stk = (VisualTreeHelper.GetParent(chkbox)) as StackPanel;
TextBlock tb = (stk.FindName("txtblock")) as TextBlock;
txtbox.Text = tb.Text;
ContentPresenter tvi = (VisualTreeHelper.GetParent(VisualTreeHelper.GetParent(chkbox))) as ContentPresenter;
if (tvi != null)
{
TreeNode node = tvi.DataContext as TreeNode;
TreeViewItem tvitem = FindTreeViewItemContainer(this.TVCountry, node);
tvitem.IsSelected = true;
}
}
//找到一个TreeNode所在的TreeViewItem
public TreeViewItem FindTreeViewItemContainer(ItemsControl root, object info)
{
if (root == null) { return null; }
TreeViewItem tvi = root.ItemContainerGenerator.ContainerFromItem(info) as TreeViewItem;
if (tvi == null)
{
if (root.Items != null)
{
foreach (var item in root.Items)
{
tvi = FindTreeViewItemContainer(root.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem, info);
if (tvi != null)
{
break;
}
}
}
}
return tvi;
}
这样就完整啦。具体的效果如下图:
刚接触WPF,作为自己的一点记录,做的东西很简单,希望能和一样刚入门的朋友一起交流。