现在的位置: 首页 > 综合 > 正文

使用VisualTreeHelper获取DataTemplate中的控件

2013年10月14日 ⁄ 综合 ⁄ 共 3083字 ⁄ 字号 评论关闭

定义为DataTemplate中的控件,无法直接通过x:Name的索引方式来获取,因此必须另想办法。

在.net库中有一个VisualTreeHelper类,是专用于涉及可视化树的节点的操作用途。既然控件也存在于可视化树中,也可以使用这种方式来查找节点。

貌似还有一种方法,在DataTemplate中有LoadContent的方式,也可以获取其中的根元素。但我试了几遍,没什么反应,只好暂时作罢。下次再找原因。

下面是一个实例代码。

(1)首先是ListBox的数据源类示例:

    public class FileBrowserDataSource : INotifyPropertyChanged
    { 
        #region Data Members

        private string m_FileName;
        public string FileName
        {
            get
            {
                return m_FileName;
            }
            set
            {
                if (value != m_FileName)
                {
                    m_FileName = value;
                    NotifyPropertyChanged("FileName");
                }
            }
        }

        private string m_CreateDate;
        public string CreateDate
        {
            get
            {
                return m_CreateDate;
            }
            set
            {
                if (value != m_CreateDate)
                {
                    m_CreateDate = value;
                    NotifyPropertyChanged("CreateDate");
                }
            }
        }

        #endregion

        #region Constructor

        public FileBrowserDataSource(string fileName, string date)
        {
            FileName = fileName;
            CreateDate = date;
        }

        #endregion

        #region Event Handler

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(String propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (null != handler)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }

(2)接着是在一个页面xaml中定义了ListPicker和一个用于测试的button:

        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0" Height="400" Background="CadetBlue">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>

            <ListBox x:Name="FileListBox" Grid.Row="0"
                     ItemsSource="{Binding}"
                     Height="200">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal"> 
                            <CheckBox  Content="{Binding FileName}" VerticalAlignment="Center"/>
                            <TextBlock Margin="20 0 0 0" Text="{Binding CreateDate}" VerticalAlignment="Center"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            
            <Button Click="OnButtonClick" Content="Count Selected Files" Grid.Row="1" Height="80" Background="Chartreuse"/>
        </Grid>

(3)最后是ListPicer的后台代码:

    public partial class TestListPicker : PhoneApplicationPage
    {
        public TestListPicker()
        {
            InitializeComponent();

            List<FileBrowserDataSource> list = new List<FileBrowserDataSource>();
            list.Add(new FileBrowserDataSource("headFile","20120924"));
            list.Add(new FileBrowserDataSource("midFile", "20120925"));
            list.Add(new FileBrowserDataSource("tailFile", "20120925"));

            FileListBox.ItemsSource = list;
        }

        private void OnButtonClick(object sender, EventArgs e)
        {
            string selectedFiles = string.Empty;

            for (int i = 0; i < this.FileListBox.Items.Count; i++)
            {
                ListBoxItem item = this.FileListBox.ItemContainerGenerator.ContainerFromIndex(i) as ListBoxItem;

                TextBlock txtBlock = SearchVisualTree<TextBlock>(item);
                CheckBox chkBox = SearchVisualTree<CheckBox>(item);

                if (chkBox.IsChecked == true)
                {
                    selectedFiles += (txtBlock.Text.ToString() + " ");
                }
            }

            if (selectedFiles != string.Empty)
            {
                selectedFiles = "files selected: " + selectedFiles;
                MessageBox.Show(selectedFiles);
            }
            else
            {
                MessageBox.Show("No file Selected");
            }
        }

        private T SearchVisualTree<T>(DependencyObject tarElem) where T:DependencyObject
        {
            var count = VisualTreeHelper.GetChildrenCount(tarElem);
            if (count == 0)
                return null;

            for (int i = 0; i < count; ++i)
            {
                var child = VisualTreeHelper.GetChild(tarElem, i);
                if (child != null && child is T)
                {
                    return (T)child;
                }
                else
                {
                    var res = SearchVisualTree<T>(child);
                    if (res != null)
                    {
                        return res;
                    }
                }
            }

            return null;
        }
}

(4)运行效果:

最后还有一个问题没有解决,就是在后台代码中我想动态设置空间的Binding数据源(通过SetBinding方法),但是失败了,暂时头脑有点乱。迟点再解决吧。有高手在这里的话麻烦指教一下,不胜荣幸。

抱歉!评论已关闭.