在XAML中声明控件而不将其添加到Visual Tree

时间:2016-08-14 12:20:52

标签: c# xaml uwp

我想在Xaml中创建Control,但我可以使用C#代码创建此Control,但不知怎的,它太冗长了。

所以我在Control中使用Page.Resources声明了这个x:Name="UserControl"

在运行时,我会将此UserControl附加到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
}

运行时,我收到COMException消息:WinRT information: Element is already the child of another element

我检查Parent中的属性UserControl为空,这个异常怎么会发生?

如何在XAML中声明Control而不将其添加到Visual Tree?

2 个答案:

答案 0 :(得分:2)

如果要在XAML中创建可重复使用的控件,请在项目中添加UserControl

UserControl

接下来,在此新文件中添加控件中的内容:

<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>

现在,您可以在页面上的XAML中使用此控件任意次数

<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>

或者在代码背后,请注意您必须在此处创建新对象。

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

用户控件是与您的页面分开的实体。如果要使用事件,请选中this reply(与WPF中的相同)。如果您想添加自定义属性,请阅读Dependency Properties

编辑:如果您不想要控制可重用性并且只想在页面上声明控件,请在Grid内部而不是Page.Resources中执行。然后,没有必要尝试在后面的代码中创建它。

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

答案 1 :(得分:0)

我通过创建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);
          }
      }
}

然后我可以添加任何UIElement,而不添加VisualTree

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