服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C# WPF 父控件通过使用可视化树找到子控件的示例代码

C# WPF 父控件通过使用可视化树找到子控件的示例代码

2022-02-28 13:27hello黄先森 C#

这篇文章主要介绍了C# WPF 父控件通过使用可视化树找到子控件的示例代码,需要的朋友可以参考下

在我们使用wpf设计前台界面时,经常会重写数据模板,或者把控件放到数据模板里。但是一旦将控件放到数据模板中,在后台就没有办法通过控件的名字来获取它了,更没办法对它进行操作(例如,隐藏,改变控件的某个值)。

如果你是比我还白的小白,对我刚刚陈述的东西不清楚,接下来我简单说一下什么是把控件放在数据模板中,怎么样的情况没法后台通过名字来获取控件,如果读者对于数据模板这些事儿已经清楚了,或者只关心如何使用可视化树可以将这部分跳过哈。

先上代码介绍一下什么是数据模板以wpf中listbox控件为例:

?
1
2
3
4
5
6
7
<listbox name="listbox_1" horizontalalignment="left" height="299" margin="10,10,0,0" verticalalignment="top" width="497" mousedoubleclick="listbox_1_onmousedoubleclick">
    <listbox.itemtemplate>
      <datatemplate>
        <button name="button_1" content="666"></button>
      </datatemplate>
    </listbox.itemtemplate>
</listbox>

我在后台设置了显示了8行item,效果如下:

C# WPF 父控件通过使用可视化树找到子控件的示例代码

我们可以看到重写数据模板实现的效果是在listbox的每一项item都是一个button,这里介绍的只是一些简单应用例子,重写模板是很强大的。因为如果用到可视化树多半是因为使用了数据模板在后台用名字无法找到相应控件了,所以在此简单介绍一下,方便理解。

接下来我们在后台尝试通过控件的名字来找到我们的listbox和button

C# WPF 父控件通过使用可视化树找到子控件的示例代码

C# WPF 父控件通过使用可视化树找到子控件的示例代码

我们发现通过控件的名字可以找到listbox但是通过button的名字却无法找到button,这就是数据模板搞的鬼。

但是没有关系,我们可以通过可视化树从listbox里找到它的子控件我们想要的这个button。

重点来了,先上代码,可视化树通过父控件找到它的子控件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
list<t> findvisualchild<t>(dependencyobject obj) where t : dependencyobject
    {
      try
      {
        list<t> list = new list<t>();
        for (int i = 0; i < visualtreehelper.getchildrencount(obj); i++)
        {
          dependencyobject child = visualtreehelper.getchild(obj, i);
          if (child is t)
          {
            list.add((t)child);
            list<t> childofchildren = findvisualchild<t>(child);
            if (childofchildren != null)
            {
              list.addrange(childofchildren);
            }
          }
          else
          {
            list<t> childofchildren = findvisualchild<t>(child);
            if (childofchildren != null)
            {
              list.addrange(childofchildren);
            }
          }
        }
        return list;
      }
      catch (exception)
      {
        //messagebox.show(ee.message);
        return null;
      }
    }

先将上面的方法复制到你的项目当中,此时对于可视化树的应用已经完成一半了。

接下来上代码,通过可视化树双击listbox的ltem把对应的button的content值从666改成777:

C# WPF 父控件通过使用可视化树找到子控件的示例代码

?
1
2
3
4
5
6
7
8
9
private void listbox_1_onmousedoubleclick(object sender, mousebuttoneventargs e)
    {
      listboxitem mylistboxitem = (listboxitem)listbox_1.itemcontainergenerator.containerfromitem(listbox_1.selecteditem);
      list<button> btnlist = findvisualchild<button>(mylistboxitem);
      foreach (var item in btnlist)
      {
        item.content = "777";
      }
    }

效果就是双击哪个item哪个item中的button从666变成了777。

我们通过父控件找到了里面的子控件button,我们便可以对它进行任何操作(和用名字找到是一样的)。

以上关于可视化树的代码可以应用于listbox,datagrid,listview,treeview,对于“.itemcontainergenerator.containerfromitem”这段代码的含义我暂时不是很理解,欢迎指教和交流。

通过以上的例子相信读者已经可以使用可视化树找到相应的控件了,但在我的开发过程中曾遇到过一些问题,和对于使用可视化树的一点小建议。

1.如果你在使用可视化树执行“listboxitem mylistboxitem = (listboxitem)listbox_1.itemcontainergenerator.containerfromitem(listbox_1.selecteditem);”这句返回值是空(实际上不是空),可能是因为界面没有初始化完毕,我的理解是,在前台这个控件还没生成完毕,或者是你修改了值但前台还没有修改,可以加上这句:

控件名.updatelayout();

之后在使用可视化树,这一条的说法和形容可能有点不严谨,欢迎指正交流。

2.可视化树使用的是递归的方法,所以它的效率不是很高,如果在程序中大量使用可视化树,会使得程序变慢的。

3.调用可视化树返回的列表如果没有找到相应的控件或是异常便会返回空值,所以建议在你遍历可视化树返回的列表时,请先判断否非为空。

补充:wpf查找子控件和父控件方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
一、查找某种类型的子控件,并返回一个list集合
public list<t> getchildobjects<t>(dependencyobject obj, type typename) where t : frameworkelement
{
dependencyobject child = null;
list<t> childlist = new list<t>();
for (int i = 0; i <= visualtreehelper.getchildrencount(obj) - 1; i++)
{
child = visualtreehelper.getchild(obj, i);
if (child is t && (((t)child).gettype() == typename))
{
childlist.add((t)child);
}
childlist.addrange(getchildobjects<t>(child,typename));
}
return childlist;
}
调用:
list<button> listbuttons = getchildobjects<button>(parentpanel, typeof(button)); //parentpanel就是xaml里定义的控件的x:name
二、通过名称查找子控件,并返回一个list集合
public list<t> getchildobjects<t>(dependencyobject obj, string name) where t : frameworkelement
{
dependencyobject child = null;
list<t> childlist = new list<t>();
for (int i = 0; i <= visualtreehelper.getchildrencount(obj) - 1; i++)
{
child = visualtreehelper.getchild(obj, i);
if (child is t && (((t)child).gettype() == name |string.isnullorempty(name)))
{
childlist.add((t)child);
}
childlist.addrange(getchildobjects<t>(child,name));
}
return childlist;
}
调用:
list<button> listbuttons = getchildobjects<button>(parentpanel, "button1");
三、通过名称查找某子控件:
public t getchildobject<t>(dependencyobject obj, string name) where t : frameworkelement
{
dependencyobject child = null;
t grandchild = null;
for (int i = 0; i <= visualtreehelper.getchildrencount(obj) - 1; i++)
{
child = visualtreehelper.getchild(obj, i);
if (child is t && (((t)child).name == name | string.isnullorempty(name)))
{
return (t)child;
}
else
{
grandchild = getchildobject<t>(child, name);
if (grandchild != null)
return grandchild;
}
}
returnnull;
}
调用:
stackpanel sp = getchildobject<stackpanel>(this.layoutroot, "spdemopanel");
四、通过名称查找父控件
public t getparentobject<t>(dependencyobject obj, string name) where t : frameworkelement
{
dependencyobject parent = visualtreehelper.getparent(obj);
while (parent != null)
{
if (parent is t && (((t)parent).name == name | string.isnullorempty(name)))
{
return (t)parent;
}
parent = visualtreehelper.getparent(parent);
}
returnnull;
}
调用:
grid layoutgrid = vthelper.getparentobject<grid>(this.spdemopanel, "layoutroot");

总结

以上所述是小编给大家介绍的c# wpf 父控件通过使用可视化树找到子控件,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!

原文链接:https://www.cnblogs.com/hellohxs/p/9528408.html

延伸 · 阅读

精彩推荐
  • C#C#微信公众号与订阅号接口开发示例代码

    C#微信公众号与订阅号接口开发示例代码

    这篇文章主要介绍了C#微信公众号与订阅号接口开发示例代码,结合实例形式简单分析了C#针对微信接口的调用与处理技巧,需要的朋友可以参考下...

    smartsmile20127762021-11-25
  • C#利用C#实现网络爬虫

    利用C#实现网络爬虫

    这篇文章主要介绍了利用C#实现网络爬虫,完整的介绍了C#实现网络爬虫详细过程,感兴趣的小伙伴们可以参考一下...

    C#教程网11852021-11-16
  • C#三十分钟快速掌握C# 6.0知识点

    三十分钟快速掌握C# 6.0知识点

    这篇文章主要介绍了C# 6.0的相关知识点,文中介绍的非常详细,通过这篇文字可以让大家在三十分钟内快速的掌握C# 6.0,需要的朋友可以参考借鉴,下面来...

    雨夜潇湘8272021-12-28
  • C#VS2012 程序打包部署图文详解

    VS2012 程序打包部署图文详解

    VS2012虽然没有集成打包工具,但它为我们提供了下载的端口,需要我们手动安装一个插件InstallShield。网上有很多第三方的打包工具,但为什么偏要使用微软...

    张信秀7712021-12-15
  • C#如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    这篇文章主要给大家介绍了关于如何使用C#将Tensorflow训练的.pb文件用在生产环境的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴...

    bbird201811792022-03-05
  • C#深入理解C#的数组

    深入理解C#的数组

    本篇文章主要介绍了C#的数组,数组是一种数据结构,详细的介绍了数组的声明和访问等,有兴趣的可以了解一下。...

    佳园9492021-12-10
  • C#SQLite在C#中的安装与操作技巧

    SQLite在C#中的安装与操作技巧

    SQLite,是一款轻型的数据库,用于本地的数据储存。其优点有很多,下面通过本文给大家介绍SQLite在C#中的安装与操作技巧,感兴趣的的朋友参考下吧...

    蓝曈魅11162022-01-20
  • C#C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    这篇文章主要介绍了C#设计模式之Strategy策略模式解决007大破密码危机问题,简单描述了策略模式的定义并结合加密解密算法实例分析了C#策略模式的具体使用...

    GhostRider10972022-01-21