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

t0ybt7op  于 2022-12-07  发布在  其他
关注(0)|答案(2)|浏览(301)

我创建了一个 UserControl。它包含几个特定样式的元素,并有一个 DockPanel 来包含后来添加到 MainWindow.xaml 上的子元素。它工作正常,并可以在 MainWindow.xaml 上拥有它的子元素。但当您在任何子元素上设置 Name 属性时,它在编译时产生“名称已被使用”异常。我还需要考虑什么?如果不设置 Name 属性,它就可以正常工作。
异常:无法在元素“TextBlock”上设置Name特性值“ThisProduceAnError.”“TextBlock”位于元素“PropertyPanel”得范围内,而该元素在另一个范围中定义时已注册了名称.

用户控件.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>

用户控件. 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());
        }
}

主窗口.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>
w6mmgewl

w6mmgewl1#

不使用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());
    }

}
wydwbb8l

wydwbb8l2#

我犯了上面提到的错误。我在Studio创建的XAML中安装了模板。当您添加用户控件时,它会从两个文件创建代码:XAML和Code-Benind中的分部类。
对于默认元素,实现是不同的。C#中具有属性的单独类和具有此类模板的单独XAML主题。请查看自定义元素是如何实现的。
为了简化示例,我没有设置主题,而是在窗口资源中创建了一个默认样式。
使用者控件的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));
    }

}

Windows的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"
        >
    <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>

相关问题