从分配有 ControlTemplate 的 UWP 控件实例访问元素

Posted

技术标签:

【中文标题】从分配有 ControlTemplate 的 UWP 控件实例访问元素【英文标题】:Access an element from UWP control instance that has a ControlTemplate assigned to it 【发布时间】:2022-01-07 14:28:05 【问题描述】:

我在MainPage.xaml 中有以下代码:

<Page ...>
   <VariableSizedWrapGrid Name="ContentGrid"/>
</Page>

只是一个原始标记来创建一个包含一些 CalendarView 实例的网格控件。\

然后在MainPage.xaml.cs 中生成几个日历:

namespace App1 

    public sealed partial class MainPage : Page 

        public MainPage() 
            this.InitializeComponent();
            for (int i = 1; i <= 12; i++)
            
                CalendarView instance = new CalendarView();
                instance.CalendarViewDayItemChanging += myEvent;
                ContentGrid.Children.Add(instance);
            
        

        private void myEvent(CalendarView sender, CalendarViewDayItemChangingEventArgs args)...

    

但是,这些日历的内部内容具有覆盖App.xaml 中定义的样式

<Application ...>
    <Application.Resources>
        <ResourceDictionary>

            <Style x:Key="CalendarViewDayItemRevealStyle" TargetType="CalendarViewDayItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="CalendarViewDayItem">
                            <Grid x:Name="itemgrid" />
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

            <Style TargetType="CalendarViewDayItem" BasedOn="StaticResource CalendarViewDayItemRevealStyle" />

        </ResourceDictionary>
    </Application.Resources>
</Application>

每个日历控件实例都包含多个 CalendarViewDayItem 控件。 这些 CalendarViewDayItem 控件中的每一个都将使用上面的模板呈现其内容。

问题是:如何访问实例特定的网格元素(这里使用名称 itemgrid)?

在一个理想的世界里,我会想象这样的事情:

private void myEvent(CalendarView sender, CalendarViewDayItemChangingEventArgs args)
    CalendarViewDayItem instance = args.Item;
    ControlTemplate instance_template = instance.Template;
    Grid g = (Grid)instance_template.getValue().getElementByName("itemgrid");


我也知道只有当实例被充分构造时,这种访问才应该起作用。 此外,也许一些实例绑定巫术可以工作。 这是与How do I access an element of a control template from within code-behind 类似的问题 但我们这里是 UWP。

【问题讨论】:

你到底想做什么?当一个CalendarView 对象被渲染时,它会调用CalendarViewDayItemChanging 数百次。 @RoyLi-MSFT 当发生任何CalendarViewDayItemChanging 调用时,我想访问该事件调用的 DayItem 对象,并且我想访问此 DayItem 具有的特定网格对象,网格包含在我定义的控件模板中,由于 DayItem 的控件使用这个控件模板进行渲染,所以必须有访问它的方法。然后,我想根据该特定日期项目的其他一些信息将项目添加到此网格中。 【参考方案1】:

试试这个:

     private void Instance_CalendarViewDayItemChanging(CalendarView sender, CalendarViewDayItemChangingEventArgs args)
    
        CalendarViewDayItem item = args.Item;

        Grid grid = FindMyChildByName(item, "itemgrid") as Grid;
    

public static DependencyObject FindMyChildByName(DependencyObject parant, string ControlName)
    
        int count = VisualTreeHelper.GetChildrenCount(parant);

        for (int i = 0; i < count; i++)
        
            var MyChild = VisualTreeHelper.GetChild(parant, i);
            if (MyChild is FrameworkElement && ((FrameworkElement)MyChild).Name == ControlName)
                return MyChild;

            var FindResult = FindMyChildByName(MyChild, ControlName);
            if (FindResult != null)
                return FindResult;
        

        return null;
    

【讨论】:

正是我需要的。谢谢。所以基本上我不能直接通过实例在任何地方访问元素,而是我需要将实例发送到 .NET DOM 处理器并在那里找到元素。

以上是关于从分配有 ControlTemplate 的 UWP 控件实例访问元素的主要内容,如果未能解决你的问题,请参考以下文章

故事板找不到 ControlTemplate 元素

如何从代码隐藏中访问UserControl中样式的Setter中ControlTemplate中定义的Control实例?

覆盖ControlTemplate中的属性

Xamarin - 绑定到 ControlTemplate 中的静态类

如何在此 ControlTemplate 中进行绑定?

WPF ControlTemplate简介