【问题标题】:Declaring Control in XAML Without Adding It to Visual Tree在 XAML 中声明控件而不将其添加到可视化树
【发布时间】:2016-09-03 16:56:12
【问题描述】:

我想在 Xaml 中创建 Control,但是我可以使用 C# 代码创建这个 Control,但不知何故它太冗长了。

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

在运行时,我会将这个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

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

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

【问题讨论】:

    标签: c# xaml uwp


    【解决方案1】:

    如果您想在 XAML 中创建可重复使用的控件,请将 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>
    

    【讨论】:

    • 很好,但是如果我使用event,我也必须将这个event 包装在UserControl 中。
    • 谢谢,我知道如何创建和使用 UserControl,但这并不能回答我的问题。
    • 嗯,要么是用户控制方法,要么是我回复的第二部分。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2022-10-25
      • 1970-01-01
      • 1970-01-01
      • 2013-10-31
      • 2020-03-04
      • 2011-10-30
      • 1970-01-01
      • 2023-03-21
      • 1970-01-01
      相关资源
      最近更新 更多