Chinaunix首页 | 论坛 | 博客
  • 博客访问: 49252
  • 博文数量: 21
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 190
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-24 15:25
文章分类

全部博文(21)

文章存档

2013年(21)

我的朋友

分类: C#/.net

2013-08-20 15:21:04

WPF - Find Child Control by name in WPF way

Topic: WPF - Find Child Control by name in WPF way

标题: WPF – wpf方式按名字查找子控件

我们知道windows API 暴露了一个自动化接口,该接口允许你按名字查找控件,但是为了创建一个好的工具函数,我们可以使用VisualTreeHelper列举Visual Tree以按照WPF方式按名和类型找到子控件。

We know that Windows API may has exposed some automation API that allows you to find one control by its name, while to make a good utility method, we can use the VisualTreeHelper to iterate through the Visual Tree to get the named Child control and its type.

找到工具类/方法如下

The Utility class/method that we making of is now .

    public static class VisualTreeHelperUtilities

    {

        ///

        /// Finds a Child of a given item in the visual tree.

        ///

        /// A direct parent of the queried item.

        /// The type of the queried item.

        /// x:Name or Name of child.

        /// The first parent item that matches the submitted type parameter.

        /// If not matching item can be found,

        /// a null parent is being returned.

        public static T FindChild(System.Windows.DependencyObject parent, string childName)

            where T : System.Windows.DependencyObject

        {

            // confirm parent and childName are valid

            if (parent == null) return null;

 

            T foundChild = null;

 

 

            int childrenCount = System.Windows.Media.VisualTreeHelper.GetChildrenCount(parent);

            for (int i = 0; i < childrenCount; i++)

            {

                var child = System.Windows.Media.VisualTreeHelper.GetChild(parent, i);

 

                // if hte child is not the requested child type child

                T childType  = child as T;

                if (childType == null)

                {

                    // recursively drill down the tree

                    foundChild = FindChild(child, childName);

 

                    // if the child is Found, break so we don't overwrite the found child

                    if (foundChild != null) break;

                }

                else if (!string.IsNullOrEmpty(childName))

                {

                    var frameworkElement = child as System.Windows.FrameworkElement;

                    // if the child's name is set for search

                    if (frameworkElement != null && frameworkElement.Name == childName)

                    {

                        // if the child's name is of the request name

                        foundChild = (T)child;

                        break;

 

                    }

                }

                else

                {

                    // child element found.

                    foundChild = (T)child;

                    break;

                }

            }

            return foundChild;

        }

    }

方便测试,我们创建了如下的View Model

To make an test, here is the view model code that we created. 

    public class MainWindowViewModel : INotifyPropertyChanged

    {

        #region Instance Fields

 

        private string _childNameToFound;

        private Type _childType;

        private FrameworkElement _foundChild;

        private DependencyObject _parent;

 

        #endregion

 

        #region Construction and Initialization

 

        public MainWindowViewModel(MainWindow mainwindow)

        {

            _parent = mainwindow;

        }

 

        #endregion

 

        #region Properties

 

        public string ChildNameToFound

        {

            get

            {

                return _childNameToFound;

            }

            set

            {

                _childNameToFound = value;

                RaisePropertyChanged("ChildNameToFound");

                FindChildByName();

            }

        }

 

        public Type ChildType

        {

            get

            {

                return _childType;

            }

            set

            {

                _childType = value;

                RaisePropertyChanged("ChildType");

                FindChildByName();

            }

        }

 

 

        public FrameworkElement FoundChild

        {

            get

            {

                return _foundChild;

            }

            set

            {

                _foundChild = value;

                RaisePropertyChanged("FoundChild");

            }

        }

 

        internal DependencyObject Parent

        {

            get

            {

                return _parent;

            }

        }

 

        #endregion

 

        #region INotifyPropertyChanged

 

 

        public event PropertyChangedEventHandler PropertyChanged;

 

 

        protected void RaisePropertyChanged(string propertyName)

        {

            if (propertyName == string.Empty) throw new ArgumentException("string.Empty is not allowed");

            if (propertyName == null) throw new ArgumentNullException("propertyName");

 

 

            PropertyChangedEventHandler propertyChanged = PropertyChanged;

            if (propertyChanged != null)

            {

                propertyChanged(this, new PropertyChangedEventArgs(propertyName));

            }

        }

 

 

        #endregion

 

        #region Find Child by name

 

        private void FindChildByName()

        {

            var childName = ChildNameToFound;

 

            if (ChildType == typeof(ListBox))

            {

                FoundChild = VisualTreeHelperUtilities.FindChild(Parent, childName);

            }

            else if (ChildType == typeof(TextBox))

            {

                FoundChild = VisualTreeHelperUtilities.FindChild(Parent, childName);

            }

            else if (ChildType == typeof(TextBlock))

            {

                FoundChild = VisualTreeHelperUtilities.FindChild(Parent, childName);

            }

            else if (ChildType == typeof(ComboBox))

            {

                FoundChild = VisualTreeHelperUtilities.FindChild(Parent, childName);

            }

        }

        #endregion

    }

View Model 是按照如下的方法连接到MainWindow上的。

The view model is thus wired up to the MainWindow (the view) as such..

    public partial class MainWindow : Window

    {

        public MainWindow()

        {

            InitializeComponent();

 

            this.DataContext = new MainWindowViewModel(this);

        }

    }

 

如下是我们该怎么定义这个View的。

Here comes how we define the view.


        xmlns=""

        xmlns:x=""

        xmlns:sys="clr-namespace:System;assembly=mscorlib"

        Title="MainWindow" Height="350" Width="525">

   

 

       

           

           

           

       

       

       

            x:Name="ChildNameToFoundText"

            Text="{Binding ChildNameToFound}"

            Grid.Row="0"

            Visibility="Collapsed"

            />

       

       

            x:Name="ChildNameToFound"

            Grid.Row="0"

            SelectedItem="{Binding ChildNameToFound, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

            >

           

                ChildNameToFoundText

                ChildNameToFound

                ChildType

                FoundChild

           

       

           

       

            x:Name="ChildType"

            Grid.Row="1"

            SelectedItem="{Binding ChildType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"

            >

           

               

               

               

           

      

       

       

            x:Name="FoundChild"

            Text="{Binding FoundChild}"

            Grid.Row="2"

            >

       

   


程序开始的时候,你得到如下的

When the program start, here is what you get.





引用:

References:


阅读(3364) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~