1

I want to create Control in Xaml, I can however create this Control using C# code, but somehow it's too verbose.

So I declare this Control in Page.Resources with x:Name="UserControl".

On runtime I will attach this UserControl to the Grid.

Page.xaml :

<Page Loaded="OnLoaded">
   <Page.Resources>
      <UserControl x:Name="UserControl">
                <TextBlock>Hi, There</TextBlock>
      </UserControl>
   </Page.Resources>
   <Grid x:Name="Grid">
   </Grid>
</Page>

Page.xaml.cs

private void OnLoaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
   Grid.Children.Add(UserControl); // exception
}

When running this, I got COMException with message: WinRT information: Element is already the child of another element.

I check property Parent in UserControl is null, how can this exception happen ?

How to declare Control in XAML without adding it to Visual Tree ?

Ask Too Much
  • 627
  • 4
  • 19

2 Answers2

2

If you want to create a re-usable control in XAML, add a UserControl to your project.

UserControl

Next, add whatever has to be in your control in this new file:

<UserControl
    x:Class="App13.MyUserControl1"
    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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">

    <TextBlock>Hi, There</TextBlock>
</UserControl>

Now you can use this control any amount of times either in XAML on your page

<Page
    x:Class="App13.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App13"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel  x:Name="MyStackPanel">
            <!-- Stack the control 4 times -->
            <local:MyUserControl1 />
            <local:MyUserControl1 />
            <local:MyUserControl1 />
            <local:MyUserControl1 />
        </StackPanel>
    </Grid>
</Page>

Or in code behind, note that you'll have to create a new object here.

// add 2 more
MyStackPanel.Children.Add(new MyUserControl1());
MyStackPanel.Children.Add(new MyUserControl1());

A user control is a separate entity from your page. If you want to use events, check this reply (works the same as in WPF). If you want to add custom properties, read up on Dependency Properties.


Edit: If you don't want control re-usability and just want to declare a control on your page, do it inside the Grid instead of Page.Resources. Then there's no need to try and create it in code behind.

<Page>
   <Page.Resources>
   </Page.Resources>
   <Grid x:Name="Grid">
      <TextBlock>Hi, There</TextBlock>
   </Grid>
</Page>
Community
  • 1
  • 1
Bart
  • 9,925
  • 7
  • 47
  • 64
0

I solve this by creating DependencyProperty,

public class MyPage : Page
{
      public static readonly DependencyProperty HeaderTemplateProperty =
         DependencyProperty.Register(nameof(HeaderTemplate), 
         typeof(UIElement), typeof(MyPage), new PropertyMetadata(null));

      public UIElement HeaderTemplate
      {
          get
          {
              return (UIElement)GetValue(HeaderTemplateProperty);
          }
          set
          {
              SetValue(HeaderTemplateProperty, value);
          }
      }
}

Then I can add any UIElement, without adding it VisualTree.

<Page Loaded="OnLoaded">
   <Page.HeaderTemplate>
      <UserControl x:Name="UserControl">
         <TextBlock>Hi, There</TextBlock>
      </UserControl>
   </Page.HeaderTemplate>
   <Grid x:Name="Grid">
   </Grid>
</Page>
Ask Too Much
  • 627
  • 4
  • 19