This question comes from this related question.
One way to access your nested inner control, is to create dependency-properties in the outer control and pass values to the inner control.
How can I access directly the inner control from outside the outer control?
CodePudding user response:
One way to do this, is to store the inner control in a public property.
Here's the code:
InnerControl.cs
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace WinUI3CustomControlTest;
public sealed class InnerControl : Control
{
public static readonly DependencyProperty InnerTextProperty =
DependencyProperty.Register(
nameof(InnerText),
typeof(string),
typeof(InnerControl),
new PropertyMetadata(string.Empty));
public InnerControl()
{
this.DefaultStyleKey = typeof(InnerControl);
}
public string InnerText
{
get => (string)GetValue(InnerTextProperty);
set => SetValue(InnerTextProperty, value);
}
}
OuterControl.cs
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace WinUI3CustomControlTest;
[TemplatePart(Name = nameof(MyInnerControl), Type = typeof(InnerControl))]
public sealed class OuterControl : Control
{
public OuterControl()
{
this.DefaultStyleKey = typeof(OuterControl);
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
MyInnerControl = GetTemplateChild(nameof(MyInnerControl)) as InnerControl;
}
public InnerControl? MyInnerControl { get; private set;}
}
Generic.xaml
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:WinUI3CustomControlTest">
<Style TargetType="local:OuterControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:OuterControl">
<StackPanel Orientation="Vertical">
<local:InnerControl x:Name="MyInnerControl" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="local:InnerControl">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:InnerControl">
<StackPanel>
<TextBlock Text="{TemplateBinding InnerText}" />
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
MainWindow.xaml
<Window
x:Class="WinUI3CustomControlTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:WinUI3CustomControlTest"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel>
<Button
Click="Button_Click"
Content="Set text programmatically" />
<local:OuterControl x:Name="MyOuterControl" />
</StackPanel>
</Window>
MainWindow.xaml.cs
using Microsoft.UI.Xaml;
using System;
namespace WinUI3CustomControlTest;
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (this.MyOuterControl.MyInnerControl is InnerControl innerControl)
{
innerControl.Text = DateTime.Now.ToString();
}
}
}