利用FindName找到容器中的控件

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,作为自己的一点记录,做的东西很简单,希望能和一样刚入门的朋友一起交流。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值