为了账号安全,请及时绑定邮箱和手机立即绑定

如何访问XAML DataTemplate中的控件?

/ 猿问

如何访问XAML DataTemplate中的控件?

暮色呼如 2019-09-24 14:31:34

我有这个翻转视图:


<FlipView x:Name="models_list" SelectionChanged="selectionChanged">

 <FlipView.ItemTemplate>

          <DataTemplate>

                <Grid x:Name="cv">

                        <Image x:Name="img1" Source = "{Binding ModelImage}" Stretch="Fill" Tag="{Binding ModelTag}"/>

                </Grid>

           </DataTemplate>

  </FlipView.ItemTemplate>

我想找到当前选定索引的img1。在搜索它时,我在这里的一些帖子中找到了此方法:


private DependencyObject FindChildControl<T>(DependencyObject control, string ctrlName)

    {

        int childNumber = VisualTreeHelper.GetChildrenCount(control);

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

        {

            DependencyObject child = VisualTreeHelper.GetChild(control, i);

            FrameworkElement fe = child as FrameworkElement;

            // Not a framework element or is null

            if (fe == null) return null;


            if (child is T && fe.Name== ctrlName)

            {

                // Found the control so return

                return child;

            }

            else

            {

                // Not found it - search children

                DependencyObject nextLevel = FindChildControl<T>(child, ctrlName);

                if (nextLevel != null)

                    return nextLevel;

            }

        }

        return null;

    }

它向我返回了flipview的第一个索引上的Image,但我需要当前选择的索引上存在的图像。我尝试编辑此方法,但找不到所需的控件。谁能帮我?


查看完整描述

3 回答

?
慕的地6264312

您遇到的问题DataTemplate是重复,并且内容正在生成FlipView。在Name不被暴露,因为它将与已生成的上一个兄弟(或下一个将要)发生冲突。


因此,要在中获得命名元素,DataTemplate您必须首先获取生成的项目,然后在生成的项目内部搜索所需的元素。请记住,XAML中的逻辑树是您按名称访问事物的方式。生成的项目不在逻辑树中。而是,它们在可视树中(所有控件都在可视树中)。这意味着您必须在可视树中搜索要引用的控件。将VisualTreeHelper让你做到这一点。


现在,该怎么做?


我为此写了一篇文章,因为它是一个反复出现的问题:http : //blog.jerrynixon.com/2012/09/how-to-access-named-control-inside-xaml.html,但是解决方案的实质是一个看起来像这样的递归方法:


public void TestFirstName()

{

    foreach (var item in MyFlipView.Items)

    {

        var _Container = MyFlipView.ItemContainerGenerator

            .ContainerFromItem(item);

        var _Children = AllChildren(_Container);


        var _FirstName = _Children

            // only interested in TextBoxes

            .OfType<TextBox>()

            // only interested in FirstName

            .First(x => x.Name.Equals("FirstName"));


        // test & set color

        _FirstName.Background = 

            (string.IsNullOrWhiteSpace(_FirstName.Text))

            ? new SolidColorBrush(Colors.Red)

            : new SolidColorBrush(Colors.White);

    }

}


public List<Control> AllChildren(DependencyObject parent)

{

    var _List = new List<Control>();

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)

    {

        var _Child = VisualTreeHelper.GetChild(parent, i);

        if (_Child is Control)

            _List.Add(_Child as Control);

        _List.AddRange(AllChildren(_Child));

    }

    return _List;

}

这里的关键问题是,这样的方法将获取所有子项,然后在子项控件的结果列表中可以搜索所需的特定控件。说得通?


现在回答您的问题!


因为您特别想要当前选择的项目,所以可以像这样简单地更新代码:


if (MyFlipView.SelectedItem == null)

    return;

var _Container = MyFlipView.ItemContainerGenerator

    .ContainerFromItem(MyFlipView.SelectedItem);

// then the same as above...


查看完整回答
反对 回复 2019-09-24
?
哈士奇WWW

也许更通用的方法可能是这样的:


private List<Control> AllChildren(DependencyObject parent)

{

    var _List = new List<Control>();

    for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)

    {

       var _Child = VisualTreeHelper.GetChild(parent, i);

       if (_Child is Control)

       {

        _List.Add(_Child as Control);

       }

      _List.AddRange(AllChildren(_Child));

    }

    return _List;

 } 



private T FindControl<T> (DependencyObject parentContainer, string controlName)

{            

        var childControls = AllChildren(parentContainer);

        var control = childControls.OfType<Control>().Where(x => x.Name.Equals(controlName)).Cast<T>().First();           

        return control;

}

您将这样调用FindControl:


var parentContainer = this.flipView.ItemContainerGenerator.ContainerFromItem(this.flipView.SelectedItem);

var myImage = FindControl<Image>(parentContainer, "img1");


//suppose you want to change the visibility

myImage.Visibility = Windows.UI.Xaml.Visibility.Collapsed;      


查看完整回答
反对 回复 2019-09-24
?
月关宝盒

获取对DataTemplate中元素的简单解决方案是将DataTemplate的内容包装在UserControl中,在其中您可以访问ItemsControl项中的所有UI元素。我认为FlipView通常会将其项目虚拟化,因此即使您绑定了100个项目-UI中实际上只有2-3个可能具有当前表示形式(其中1-2个处于隐藏状态),因此您必须记住当您想要替换任何内容,仅在将项目加载到控件中时才进行更改。


如果确实需要标识代表ItemsSource中项目的项目容器,则可以检查FlipView的ItemContainerGenerator属性及其ContainerFromItem()方法。


要获取项目的坐标,可以使用GetBoundingRect()WinRT XAML Toolkit中的扩展方法。


总体而言,根据您的评论,最好的方法实际上可能完全不同。如果将FlipView绑定到源,通常可以通过更改绑定的源集合项的属性来控制显示或覆盖的图像。


查看完整回答
反对 回复 2019-09-24

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信