【问题标题】:UWP MergedDictionary Style that references other style throws error引用其他样式的 UWP MergedDictionary 样式引发错误
【发布时间】:2020-04-14 23:11:31
【问题描述】:

在创建需要使用来自另一个 MergedDictionary (Brushes.xaml) 的值的样式合并字典时遇到实际问题。

当我尝试从另一个文件中引用它时,我收到以下错误:

"Failed to assign to property 'Windows.UI.Xaml.ResourceDictionary.Source' because the type 'Windows.Foundation.String' cannot be assigned to the type 'Windows.Foundation.Uri'. [Line: x Position: y]"

例如在资源字典中,我有以下工作..

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Brushes.xaml" />
    </ResourceDictionary.MergedDictionaries>
    <Style TargetType="Button">
        <Setter Property="Background" Value="{StaticResource customBrush1}" />
        <Setter Property="Foreground" Value="{StaticResource customBrush2}" />

但是,这并不理想,因为我需要在每个样式资源字典中引用 Brushes.xaml。所以我想做的是在App.xaml 中声明Brushes.xaml,但我尝试的一切都会导致上述错误。它基本上无法识别Brushes.xaml 中定义的资源,除非我将它们添加到每个单独的样式中。

例如我想要什么(能够在 App.xaml 中执行)...

<Application x:Class="Test.UWP.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             RequestedTheme="Light">
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="ms-appx:///Test.Xamarin.Forms.Themes.UWP/Brushes.xaml" />
                <ResourceDictionary Source="ms-appx:///Test.Xamarin.Forms.Themes.UWP/CustomStyles.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</Application>

CustomStyles.xaml 包含

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Styles\Button\BackButton.xaml" />
        <ResourceDictionary Source="Styles\Button\Default.xaml" />
        <ResourceDictionary Source="Styles\Button\HyperlinkBasicButton.xaml" />
        <ResourceDictionary Source="Styles\Button\HyperlinkButton.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

例如Styles\Button\Default.xaml 包含..

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Style TargetType="Button">
        <Setter Property="Background" Value="{StaticResource CustomBrush1}" />
        <Setter Property="Foreground" Value="{StaticResource CustomBrush2}" />

CustomBrush1 在Brushes.xaml 中定义。

我尝试了很多东西,例如尝试将 Brushes.xaml 添加到 CustomStyles.xaml - 不起作用。尝试将顺序更改为 this 状态它们应该以相反的顺序 - 这不起作用。

非常感谢任何帮助,谢谢

根据评论,这里是Brushes.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="CustomBrush1"
                     Color="Black}" />
    <SolidColorBrush x:Key="CustomBrush2"
                     Color="White}" />
</ResourceDictionary>

【问题讨论】:

  • 我觉得这不是合并字典的问题!您的&lt;x:String ...&gt;&lt;/x:String&gt; 之一必须更改为&lt;x:Uri&gt;&lt;/x:Uri&gt;
  • 我不明白 - 哪个字符串?谢谢
  • 您能否将您的 Brushes.xamlCustomStyles.xaml 文件上传到任何我可以下载并查看的位置?
  • CustomStyles.xaml 在原帖中,我刚刚添加了Brushes.xaml

标签: c# xaml uwp


【解决方案1】:

根据您的描述,这种行为是设计使然,我们可以找到这个document

然后查找序列检查应用程序的运行时对象树中的下一个父对象....

如果将Brushes.xaml放在专利级别,子级别Default.xaml无法获取画笔资源并抛出异常。最佳实践是在每个资源中引用Brushes.xaml,就像上面提到的第一个场景一样。

如果Brushes.xamlDefault.xaml不在同一个文件夹,我们需要使用ms-appx://方案来引用它。

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestApp.Styles.Button"
    >
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="ms-appx:///Brushes.xaml" />
    </ResourceDictionary.MergedDictionaries>
    <Style TargetType="Button">
        <Setter Property="Background" Value="{StaticResource CustomBrush1}" />
        <Setter Property="Foreground" Value="{StaticResource CustomBrush2}" />
    </Style>  
</ResourceDictionary>

然后将上面添加到CustomStyles

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:TestApp"
    >
    <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="Styles/Button/Default.xaml" />
    </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

最后,我们只需要将 CustomStyles 添加到 App.xaml 文件中的MergedDictionaries

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="CustomStyles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>

【讨论】:

  • 这就是我所做的,有点。但这意味着在CustomStyles.xaml 中引用的每种样式中,我都需要对Brushes.xaml 的引用。这并不理想,它还表现出我现在不会讨论的不可预测的行为。但无论如何,我找到了一个解决方案,我将在接下来发布。此外,据我了解,仅当文件位于不同的程序集中时才需要使用 ms-appx:///
【解决方案2】:

我找到了解决这个问题的方法。问题是一个资源字典不能引用另一个资源字典中的任何内容,如果它们都在 App.Xaml 中声明(除非值在 ControlTemplate 中 - 见下文)

我找到的解决方案是从App.Xaml中删除所有资源字典,所以App.Xaml基本上是这样的:

<Application x:Class="Dwp.CRMobile.UWP.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             RequestedTheme="Light">
</Application>

然后将它们添加到App.Xaml.csOnLaunched 方法中,如下所示。请注意,如果应用程序也可以通过 PowerShell 等运行,您还需要将其添加到 OnActivated

protected override void OnActivated(IActivatedEventArgs e)
{
    var eventArgs = e as ProtocolActivatedEventArgs;
    var data = new ActivationArgs(e.Kind, eventArgs.Uri.Query);

    AddResources();

    Run(e, data);
}

protected override void OnLaunched(LaunchActivatedEventArgs e)
{
#if RELEASE
    var data = new ActivationArgs(e.Kind, e.Arguments);
#else
    var data = new ActivationArgs(ActivationKind.Protocol, e.Arguments);
#endif

    AddResources();

    Run(e, data);
}

private static void AddResources()
{
    var applicationMergedDictionaries = Application.Current.Resources.MergedDictionaries;
    applicationMergedDictionaries.Add(GetResourceDictionary("ms-appx:///Test.Xamarin.Forms.Themes.UWP/Brushes.xaml"));
    applicationMergedDictionaries.Add(GetResourceDictionary("ms-appx:///Test.Xamarin.Forms.Themes.UWP/CustomStyles.xaml"));
    applicationMergedDictionaries.Add(GetResourceDictionary("ms-appx:///Test.HTMobile.Core.UWP/Styles.xaml"));
    applicationMergedDictionaries.Add(GetResourceDictionary("ms-appx:///Test.CRFramework.Xamarin.Forms.UWP/Root.xaml"));
}

这是一个奇怪的问题 - 与加载资源时有关。因为如果我坚持App.xaml 中的原始方法并以CustomStyles.xaml 中定义的样式使用Brushes.xaml 中的值,如果该值设置在ControlTemplate 中,它将起作用,但是如果它在标准的 Setter 属性中,则不会。上面的这个方法为我解决了这个问题,所以希望它可以帮助其他人。

【讨论】:

    【解决方案3】:

    虽然这种行为是设计使然,但您不应该尝试直接引用外部资源字典(样式或主题),因为这会在两个文件之间创建紧密耦合的关系,以至于您不妨只做他们是一个文件。

    为避免这种情况,请在 CustomStyles.xaml 的标头中为您需要引用的资源创建 stub 定义,这有多种用途:

    1. 您已经记录了资源字典所依赖的资源
    2. 您可以声明所需资源的默认定义,进一步记录您的自定义样式,同时确保您的资源能够正常工作,即使消费者没有引用外部资源 (Brushes.xaml )
      • 顺便说一句,这首先是错误的原因。
      • 您不必包含真正的定义,但作为最佳实践,您确实应该包含。如果Brushes.xaml 将一直包含在内,那么您的存根应该 每次都被覆盖,但是因为我们无法控制Brushes.xaml 的方式或是否 已定义,最好包含所需资源的真实和完整定义。

    所以,是的,您可以偷懒,将整个 Brushes.xaml 直接插入到您的 CustomStyles.xaml 中,但是您应该只插入 CustomStyles.xaml 实际需要的资源

    这是覆盖标准 UWP 控件模板的标准方法,经过几次之后,它就会成为第二天性,如果您在设计器中右键单击控件并选择 Edit Template,Visual Studio 甚至会为您执行此操作em> 然后编辑副本...
    它将注入所选控件引用但未在全局通用 UWP 资源中定义的资源的所有定义。

    最后,当您在合并的字典中引用 CustomStyles.xaml 时,包括对 Brushes.xaml 的引用之后,这将使 Brusjes.xaml 覆盖 存根 定义您包含在CustomStyles.xaml 中。

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="CustomStyles.xaml"/>
                <ResourceDictionary Source="Brushes.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
    

    【讨论】:

      猜你喜欢
      • 2013-05-12
      • 1970-01-01
      • 2019-08-20
      • 1970-01-01
      • 2020-09-29
      • 2016-04-19
      • 1970-01-01
      • 2011-04-01
      • 1970-01-01
      相关资源
      最近更新 更多