首页 > 解决方案 > 我可以通过使用样式/资源从我的所有用户控件中删除 xmlns 标签(也许还有资源)吗?

问题描述

我想摆脱每个或文件中的xmlns标签。UserControlWindow

我可以通过某种方式使用样式或资源来做到这一点吗?

我的许多用户控件如下所示:

<UserControl x:Class="Mst2.View.Controls.Modules.TimerEntryControl"
            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:bcp="clr-namespace:ABitOfBinding"
             xmlns:dc="clr-namespace:Mst2.Dictionaries"
             xmlns:vm="clr-namespace:Mst2.ViewModel"
             xmlns:vc="clr-namespace:Mst2.ValueConverters"
             xmlns:c="clr-namespace:Mst2.View.Controls"
             xmlns:mw="clr-namespace:Mst2.View.Windows"
             mc:Ignorable="d"
             d:DesignHeight="450" d:DesignWidth="800">

    <UserControl.Resources>
        <dc:Mst2Dictionaries x:Key="Dictionaries" />
        <bcp:ByteBit2Bool x:Key="ByteBit2Bool" />
        <BooleanToVisibilityConverter x:Key="BoolToVis" />
        <vc:TimerTimeAndRangeConverter x:Key="TimerTimeAndRangeConverter"/>
    </UserControl.Resources>

    <!-- user control contents here -->

</UserControl>

标签: wpfxaml.net-4.8

解决方案


如果您从特定命名空间实例化资源,则必须声明它。解析器如何知道您指的是哪种类型?但是,如果这些资源位于单独的程序集中,则可以创建自定义 XAML 命名空间并将所有 CLR 命名空间映射到它。如果资源和命名空间是在同一个程序集中定义的,这将不起作用。

XmlnsDefinition使用所需的 XML 命名空间为每个 CLR 命名空间添加一个属性。

基于每个程序集指定 XAML 命名空间和 CLR 命名空间之间的映射,然后由 XAML 对象编写器或 XAML 架构上下文用于类型解析。

XmlnsDefinitionAttribute采用两个参数:XML/XAML 命名空间名称和 CLR 命名空间名称。可以存在多个XmlnsDefinitionAttribute将多个 CLR 命名空间映射到同一个 XML 命名空间的方法。

您需要在程序集级别插入属性,因此您必须拥有或能够修改它。

这个属性 ,XmlnsDefinitionAttribute放置在生成程序集的源代码中的程序集级别。

例如,对于您的Mst2程序集,其中的属性AssemblyInfo.cs可能如下所示。您可以自由选择 URI,它在这里除了作为标识符之外没有特殊含义。

[assembly: XmlnsDefinition("http://schemas.Mst2.com/2021", "Mst2.Dictionaries")]
[assembly: XmlnsDefinition("http://schemas.Mst2.com/2021", "Mst2.ViewModel")]
[assembly: XmlnsDefinition("http://schemas.Mst2.com/2021", "Mst2.ValueConverters")]
[assembly: XmlnsDefinition("http://schemas.Mst2.com/2021", "Mst2.View.Controls")]
[assembly: XmlnsDefinition("http://schemas.Mst2.com/2021", "Mst2.View.Windows")]

此外,您可以定义XmlPrefix一个提示设计者在将 XAML 命名空间添加到 XAML 文件时使用此前缀。

[assembly: XmlnsPrefix("http://schemas.Mst2.com/2021", "mst2")]

请注意,Visual Studio 等设计人员会尊重这一点,但其他人可能不会。

在 XAML 文件中写入元素和属性(序列化)或与具有 XAML 编辑功能的设计环境交互时,标识与 XAML 命名空间相关联的推荐前缀。

XAML 处理器或包含 XAML 的框架,或任何执行 XAML 序列化的进程,通常应遵循推荐的前缀。

当使用控件中的命名空间(在不同的程序集中)时,它看起来像这样。

<UserControl x:Class="Mst2.View.Controls.Modules.TimerEntryControl"
            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:mst2="http://schemas.Mst2.com/2021"
             xmlns:bcp="clr-namespace:ABitOfBinding"
             mc:Ignorable="d"
             d:DesignHeight="450" d:DesignWidth="800">

    <UserControl.Resources>
        <mst2:Mst2Dictionaries x:Key="Dictionaries" />
        <mst2:ByteBit2Bool x:Key="ByteBit2Bool" />
        <BooleanToVisibilityConverter x:Key="BoolToVis" />
        <mst2:TimerTimeAndRangeConverter x:Key="TimerTimeAndRangeConverter"/>
    </UserControl.Resources>

    <!-- user control contents here -->

</UserControl>

您可以做的另一件事是为共享资源创建资源字典,例如:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:bcp="clr-namespace:ABitOfBinding"
                    xmlns:dc="clr-namespace:Mst2.Dictionaries"
                    xmlns:vc="clr-namespace:Mst2.ValueConverters">
   <dc:Mst2Dictionaries x:Key="Dictionaries" />
   <bcp:ByteBit2Bool x:Key="ByteBit2Bool" />
   <BooleanToVisibilityConverter x:Key="BoolToVis" />
   <vc:TimerTimeAndRangeConverter x:Key="TimerTimeAndRangeConverter"/>
</ResourceDictionary>

然后,您可以在任何需要它的地方包含它,而不必为每个资源指定命名空间或每次都重新声明资源。

<UserControl x:Class="Mst2.View.Controls.Modules.TimerEntryControl"
            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:bcp="clr-namespace:ABitOfBinding"
             xmlns:vm="clr-namespace:Mst2.ViewModel"
             xmlns:mw="clr-namespace:Mst2.View.Windows"
             mc:Ignorable="d"
             d:DesignHeight="450" d:DesignWidth="800">

    <UserControl.Resources>
        <ResourceDictionary>
            <BooleanToVisibilityConverter x:Key="BoolToVis" />
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="MySharedResources.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </UserControl.Resources>

    <!-- User control contents here -->

</UserControl>

如果这些是公共资源,您也可以简单地将它们添加到应用程序资源字典中,然后它们将在每个控件中可用,无需任何麻烦。


推荐阅读