【问题标题】:Unable to set Name property of child controls on UserControl无法在 UserControl 上设置子控件的 Name 属性
【发布时间】:2020-06-27 16:12:24
【问题描述】:

我创建了一个 UserControl。它包含几个特定样式的元素,并有一个 DockPanel 来包含稍后在 MainWindow.xaml 上添加的子项。 它可以正常工作,并且可以在 MainWindow.xaml 上拥有它的子级。但是,当您在任何子项上设置 Name 属性时,它会在编译时产生“名称已被使用”异常。 我还需要考虑什么?不设置 Name 属性,它可以正常工作。

异常:无法在元素“TextBlock”上设置名称属性值“ThisProduceAnError”。 “TextBlock”在元素“PropertyPanel”的范围内,当它在另一个范围内定义时,它已经注册了一个名称。

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

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

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

【问题讨论】:

  • 能否请您添加整个异常?
  • 我在帖子中添加了整个异常。
  • 在我的原始代码中,它还有其他东西,如折叠按钮、事件、处理程序等。我不知道如何只用 ContentControl 和它的样式模板来处理这些东西。

标签: c# wpf xaml


【解决方案1】:

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

}

【讨论】:

  • 好的。它现在适用于您的解决方案。谢谢。您能解释一下为什么 xaml 方式会导致问题吗?如果您创建一个具有数百个元素和许多层深度的复杂 UserControl,那么在没有 xaml 的情况下处理这些复合体将太困难。难道没有办法使用xaml吗?
  • 使用 XAML 创建自己的命名空间。但特定元素不能属于两个命名空间。对于复杂元素 - 以默认元素为例。请注意,XAML 中没有填充。 XAML 用于创建模板。模板可能非常复杂。模板特异性 - 它们的命名空间与应用模板的命名空间不冲突。
  • 对不起。那么,您可以使用 XAML 通过 Style Templetes 创建一个 UseControl 吗?
  • 上一条消息我写错了。我尝试了几个选项,包括一个模板。如果使用 XAML,无论如何都会发生错误。如何解决这个问题 - 我找不到。
  • 对。感谢您的所有分享。
【解决方案2】:

我犯了上面写的错误。 我在 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));
    }

}

用于窗口的 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>

【讨论】:

    猜你喜欢
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    • 2011-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-06
    相关资源
    最近更新 更多