当前位置: 首页 > news >正文

WPF:无法对元素“XXX”设置 Name 特性值“YYY”。“XXX”在元素“ZZZ”的范围内,在另一范围内定义它时,已注册了名称。

最近在改一段 XAML 代码时,我发现无论如何给一个控件添加 Name 或者 x:Name 属性时都会出现编译错误:无法对元素“XXX”设置 Name 特性值“YYY”。“XXX”在元素“ZZZ”的范围内,在另一范围内定义它时,已注册了名称。


@TOC

编译错误

编译时,出现错误:

无法对元素“XXX”设置 Name 特性值“YYY”。“XXX”在元素“ZZZ”的范围内,在另一范围内定义它时,已注册了名称。

MC3093: Cannot set Name attribute value 'X' on element 'Y'. 'Y' is under the scope of element 'Z', which already had a name registered when it was defined in another scope.

这里的 XXX 是元素的类型,YYY 是指定的名称的值,ZZZ 是父容器的名称。

我把出现错误的 XAML 简化后大约是这样的,XXXTextBoxYYYRenameTextBox,而 ZZZwalterlv:Foo

<walterlv:Foo Background="White">
    <StackPanel Orientation="Horizontal" Focusable="False">
        <TextBlock Text="名称:" />
        <TextBox x:Name="RenameTextBox" />
    </StackPanel>
</walterlv:Foo>

小心用户控件

出现此问题的最大原因在那个 walterlv:Foo 上。实际上,这是一个用户控件,也就是继承自 UserControl 的大家通常用来写界面的东西。

<UserControl x:Class="Walterlv.Foo"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.Style>
        <!-- 省略 -->
    </UserControl.Style>
</UserControl>

别问我为什么会有以上这样诡异的代码。我也不知道,这只是偶然发现的代码,我简化后拿到博客中。

于是需要提醒大家注意:

  1. 在 WPF 里,拥有直接的 XAML 文件的始终应该作为最终用户界面,不应该当作控件使用(不要试图在其他地方使用时还设置其 Content 属性);
  2. 如果你确实希望做控件,请继承自 CustomControl 然后在 /Themes/Generic.xaml 里写样式。

至于以上 XAML 代码中我看到用的是 <UserControl.Style> 来写样式,是因为踩到了当控件用的另一个坑:

所有在控件的 XAML 中设置的 Content 属性都将被使用时覆盖。

解决方法

当然是考虑将以上诡异的用户控件定义方式改为正统的 CustomControl 啦!将 <UserControl.Style> 里定义的所有样式全部改到 /Themes/Generic.xaml 文件中。

创建自定义控件

如果你不清楚如何编写一个自定义控件,那么请直接在 Visual Studio 中基于 WPF 自定义控件创建文件,你会发现 Visual Studio 为你写好了注释。

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Walterlv.Demo
{
    /// <summary>
    /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
    ///
    /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:Walterlv.Demo"
    ///
    ///
    /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
    /// 元素中:
    ///
    ///     xmlns:MyNamespace="clr-namespace:Walterlv.Demo;assembly=Walterlv.Demo"
    ///
    /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
    /// 并重新生成以避免编译错误:
    ///
    ///     在解决方案资源管理器中右击目标项目,然后依次单击
    ///     “添加引用”->“项目”->[浏览查找并选择此项目]
    ///
    ///
    /// 步骤 2)
    /// 继续操作并在 XAML 文件中使用控件。
    ///
    ///     <MyNamespace:Foo/>
    ///
    /// </summary>
    public class Foo : Control
    {
        static Foo()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Foo), new FrameworkPropertyMetadata(typeof(Foo)));
        }
    }
}

/Themes/Generic.xaml 文件:

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:Walterlv.Demo">


    <Style TargetType="{x:Type local:Foo}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:Foo}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

我的博客会首发于 https://blog.walterlv.com/,而 CSDN 会从其中精选发布,但是一旦发布了就很少更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

知识共享许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

相关文章:

  • 一点点从坑里爬出来:如何正确打开 WPF 里的 Popup?
  • Windows Linux 系统中获取端口被哪个应用程序占用
  • 设置用户无需密码自动登录到 Windows 系统
  • 最简单的代码,让 WPF 支持响应式布局
  • 当无边框窗口被子窗口遮挡导致难以调节窗口大小时,可通过处理 NCHITTEST 消息重新支持调节窗口大小
  • 如何给 GitHub Pages 配置多个域名?
  • 通过子类化窗口(SubClass)来为现有的某个窗口添加新的窗口处理程序(或者叫钩子,Hook)
  • .NET Framework 和 .NET Core 在默认情况下垃圾回收(GC)机制的不同(局部变量部分)
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .NET 将混合了多个不同平台(Windows Mac Linux)的文件 目录的路径格式化成同一个平台下的路径
  • git 乱改你的换行符?一句话设置让 git 不再碰你某个文件的换行符
  • Linux Shell 中需要转义的字符
  • Unity3D 入门:Unity Editor 编辑器常用快捷键
  • Unity3D 入门:Unity 项目版本管理建议使用的 .gitignore 忽略文件和 .gitattributes 文件(2020年4月更新)
  • Unity3D 入门:让 C# 脚本公开可在 Unity 编辑器中设置的属性
  • Angular Elements 及其运作原理
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Laravel深入学习6 - 应用体系结构:解耦事件处理器
  • python docx文档转html页面
  • 测试如何在敏捷团队中工作?
  • 互联网大裁员:Java程序员失工作,焉知不能进ali?
  • 容器化应用: 在阿里云搭建多节点 Openshift 集群
  • 想使用 MongoDB ,你应该了解这8个方面!
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • Hibernate主键生成策略及选择
  • 国内开源镜像站点
  • 说说我为什么看好Spring Cloud Alibaba
  • #《AI中文版》V3 第 1 章 概述
  • #大学#套接字
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (java版)排序算法----【冒泡,选择,插入,希尔,快速排序,归并排序,基数排序】超详细~~
  • (solr系列:一)使用tomcat部署solr服务
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (附源码)ssm失物招领系统 毕业设计 182317
  • (四) Graphivz 颜色选择
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转)nsfocus-绿盟科技笔试题目
  • ***详解账号泄露:全球约1亿用户已泄露
  • ./include/caffe/util/cudnn.hpp: In function ‘const char* cudnnGetErrorString(cudnnStatus_t)’: ./incl
  • .Net各种迷惑命名解释
  • .NET性能优化(文摘)
  • .py文件应该怎样打开?
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...
  • @NestedConfigurationProperty 注解用法
  • @Query中countQuery的介绍
  • @基于大模型的旅游路线推荐方案
  • [ C++ ] STL priority_queue(优先级队列)使用及其底层模拟实现,容器适配器,deque(双端队列)原理了解
  • [100天算法】-x 的平方根(day 61)
  • [Android]通过PhoneLookup读取所有电话号码
  • [C/C++]数据结构----顺序表的实现(增删查改)
  • [C++基础]-初识模板
  • [FROM COM张]如何解决Nios II SBTE中出现的undefined reference to `xxx'警告
  • [GN] Vue3.2 快速上手 ---- 核心语法2