简体   繁体   English

无法在 UserControl 上设置子控件的 Name 属性

[英]Unable to set Name property of child controls on UserControl

I created a UserControl .我创建了一个UserControl It contains several elements of specific style and have a DockPanel to contain children which added later on MainWindow.xaml .它包含几个特定样式的元素,并有一个DockPanel来包含后来添加到MainWindow.xaml上的子项。 It works properly and can have it's children on MainWindow.xaml .它工作正常,可以在MainWindow.xaml上拥有它的孩子。 But when you set Name property on the any of children, It produces 'the name is aleady used' exception on compiling.但是,当您在任何子项上设置Name属性时,它会在编译时产生“名称已使用”异常。 What do I have to think more about?我还需要考虑什么? Without setting Name property, it works properly.如果不设置Name属性,它可以正常工作。

Exception: Cannot set Name attribute value 'ThisProduceAnError' on element 'TextBlock'.例外:无法在元素“TextBlock”上设置名称属性值“ThisProduceAnError”。 'TextBlock' is under the scope of element 'PropertyPanel', which already had a name registered when it was defined in another scope. “TextBlock”位于元素“PropertyPanel”的 scope 下,该名称在另一个 scope 中定义时已经注册了名称。

UserControl.xaml UserControl.xaml

<UserControl x:Class="TrainingWpf1.PropertyPanel"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:local="clr-namespace:TrainingWpf1"
    mc:Ignorable="d"
    d:DesignHeight="120" d:DesignWidth="260">
    <DockPanel>
        <TextBlock DockPanel.Dock="Top" Text="Title"/>
        <Border Padding="10" BorderThickness="1" CornerRadius="6" Background="CadetBlue">
            <DockPanel x:Name="panContent" />
        </Border>
    </DockPanel>
</UserControl>

UserControl.xaml.cs UserControl.xaml.cs

using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;

namespace TrainingWpf1
{
        [ContentProperty(nameof(Children))]
        public partial class PropertyPanel : UserControl
        {
                public PropertyPanel()
                {
                        InitializeComponent();
                        this.Children = panContent.Children;
                }

        public UIElementCollection Children
        {
                get => (UIElementCollection)GetValue(ChildrenProperty.DependencyProperty);
                private set => SetValue(ChildrenProperty, value);
        }

        public static readonly DependencyPropertyKey ChildrenProperty = DependencyProperty.RegisterReadOnly(
                nameof(Children),
                typeof(UIElementCollection),
                typeof(PropertyPanel),
                new PropertyMetadata());
        }
}

MainWindow.xaml主窗口.xaml

<Window x:Class="TrainingWpf1.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TrainingWpf1"
        mc:Ignorable="d"
        Title="MainWindow" Height="400" Width="400">
        <Grid>
                <local:PropertyPanel>
                        <TextBlock Name="ThisProduceAnError" Text="Hello"/>
                </local:PropertyPanel>
        </Grid>
</Window>

Do not use XAML:不要使用 XAML:

using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;

namespace TrainingWpf1
{
    [ContentProperty(nameof(Children))]
    public partial class PropertyPanel : UserControl
    {

        public PropertyPanel()
        {
            //InitializeComponent();

            DockPanel panContent = new DockPanel();
            this.Children = panContent.Children;
            Border border = new Border()
            {
                Padding = new Thickness(10),
                BorderThickness = new Thickness(1),
                CornerRadius = new CornerRadius(6),
                Background = Brushes.CadetBlue,
                Child = panContent
            };

            DockPanel dockPanel = new DockPanel();
            TextBlock textBlock = new TextBlock() { Text = "Title" };
            textBlock.SetValue(DockPanel.DockProperty, Dock.Top);
            dockPanel.Children.Add(textBlock);
            dockPanel.Children.Add(border);
            Content = dockPanel;
        }

        public UIElementCollection Children
        {
            get => (UIElementCollection)GetValue(ChildrenProperty.DependencyProperty);
            private set => SetValue(ChildrenProperty, value);
        }

        public static readonly DependencyPropertyKey ChildrenProperty = DependencyProperty.RegisterReadOnly(
                nameof(Children),
                typeof(UIElementCollection),
                typeof(PropertyPanel),
                new PropertyMetadata());
    }

}

I made the mistake I wrote about above.我犯了我上面写的错误。 I installed the template in XAML created by Studio.我将模板安装在 Studio 创建的 XAML 中。 When you add a user control, it creates code from two files: XAML and a partial class in Code-Benind.添加用户控件时,它会从两个文件创建代码:XAML 和 Code-Benind 中的部分 class。

For default elements, the implementation is different.对于默认元素,实现是不同的。 A separate class in C # with properties and a separate XAML theme with a template for this class. C 中的一个单独的 class # 带有属性和一个单独的 XAML 主题,带有此 ZA2F2ED4F8EBC04AB614C21A29DDC 的模板See how custom elements are implemented.查看自定义元素是如何实现的。

Having done this, I got a working code.完成此操作后,我得到了一个工作代码。 To simplify the example, I did not set a theme, but created a default style in the window resources.为了简化示例,我没有设置主题,而是在 window 资源中创建了默认样式。

C# for UserControl C# 用于用户控制

using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;

namespace TrainingWpf1
{
    [ContentProperty(nameof(Children))]
    public class PropertyPanel : UserControl
    {
        public PropertyPanel()
        {
            Children = new ObservableCollection<UIElement>();
        }

        public ObservableCollection<UIElement> Children
        {
            get => (ObservableCollection<UIElement>)GetValue(ChildrenProperty.DependencyProperty);
            private set => SetValue(ChildrenProperty, value);
        }

        public static readonly DependencyPropertyKey ChildrenProperty = DependencyProperty.RegisterReadOnly(
                nameof(Children),
                typeof(ObservableCollection<UIElement>),
                typeof(PropertyPanel),
                new PropertyMetadata(null));
    }

}

XAML for Window XAML 用于 Window

<Window x:Class="TrainingWpf1.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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TrainingWpf1"
        mc:Ignorable="d"
        Title="MainWindow" Height="400" Width="400"
        >
    <Window.Resources>
        <Style TargetType="{x:Type local:PropertyPanel}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <DockPanel>
                            <TextBlock DockPanel.Dock="Top" Text="Title"/>
                            <Border Padding="10" BorderThickness="1" CornerRadius="6" Background="CadetBlue">
                                <ItemsControl ItemsSource="{Binding Children, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:PropertyPanel}}}">
                                    <ItemsControl.ItemsPanel>
                                        <ItemsPanelTemplate>
                                            <DockPanel/>
                                        </ItemsPanelTemplate>
                                    </ItemsControl.ItemsPanel>
                                </ItemsControl>
                            </Border>
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid>
        <local:PropertyPanel>
            <TextBlock x:Name="ThisProduceAnError" Text="Hello"/>
        </local:PropertyPanel>
    </Grid>
</Window>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM