WPF:InvalidCastException:无法将“System.Windows.Style”类型的对象转换为“System.Windows.ResourceDictionary”类型

Posted

技术标签:

【中文标题】WPF:InvalidCastException:无法将“System.Windows.Style”类型的对象转换为“System.Windows.ResourceDictionary”类型【英文标题】:WPF: InvalidCastException: Unable to cast object of type 'System.Windows.Style' to type 'System.Windows.ResourceDictionary' 【发布时间】:2021-07-13 14:39:25 【问题描述】:

我尝试在我的控件中重新设置 TextBoxes 的样式,以使 ReadOnly 具有相同的外观,就好像它们被禁用一样。 上周我可以毫无问题地做到这一点:

<UserControl.Resources>
    <Style TargetType="x:Type Border" x:Key="TextBoxBorderStyle">
        <Style.Triggers>
            <DataTrigger Binding="Binding IsReadOnly, RelativeSource=RelativeSource Mode=FindAncestor, AncestorType=TextBoxBase" Value="True">
                <Setter Property="Opacity" Value="0.56"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</UserControl.Resources>

... 并像这样在 TextBoxes 中使用它:

<TextBox Text="Binding MyText"
         IsReadOnly="Binding ReadOnly"
         VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled" >
    <TextBox.Resources>
        <StaticResource ResourceKey="TextBoxBorderStyle" />
    </TextBox.Resources>
</TextBox>

我不记得在此期间更改此控件中的任何内容。 (虽然我今天将 Visual Studio 2019 更新为 16.9.4)。但是当我现在运行我的应用程序时,它给出了一个运行时错误:

System.Windows.Markup.XamlParseException HResult=0x80131501 Message='设置属性'System.Windows.FrameworkElement.Resources' 抛出异常。行号“90”和行位置“33”。 来源=PresentationFramework StackTrace:在 System.Windows.Markup.XamlReader.RewrapException(异常 e, IXamlLineInfo lineInfo, Uri baseUri)

此异常最初是在此调用堆栈中引发的: System.Windows.Baml2006.WpfSharedBamlSchemaContext.Create_BamlProperty_FrameworkElement_Resources.AnonymousMethod__276_0(对象, 目的) MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(object, System.Xaml.XamlMember, object)

内部异常 1:InvalidCastException:无法转换类型的对象 'System.Windows.Style' 输入 'System.Windows.ResourceDictionary'。

当我将样式直接复制粘贴到所有 Textbox.Resources 中时,它可以正常工作。 有谁知道为什么? 尤其是因为之前分享StaticResource 没有问题。

编辑:它在 xaml 编辑器/设计器中按预期工作,并正确地将样式调整为视图模型数据,没有任何异常。只有在运行时才会出现问题。

【问题讨论】:

确保您的目标是您之前使用的相同版本的 Net,或者执行干净的构建以使用最新版本的 Net。 我没有更改目标 .NET 版本(4.7.2),我尝试了 clean+rebuild,关闭 VS,删除 .vs 文件夹,但到目前为止没有任何帮助。一定有什么我错过了。奇怪的是它只在设计时工作(它甚至可以很好地响应我的设计时视图模型的变化) 【参考方案1】:

您应该将&lt;StaticResource ResourceKey="TextBoxBorderStyle" /&gt; 替换为实际的Style

<TextBox Text="Binding MyText"
         IsReadOnly="Binding ReadOnly"
         VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled" >
    <TextBox.Resources>
        <Style TargetType="Border" BasedOn="StaticResource TextBoxBorderStyle" />
    </TextBox.Resources>
</TextBox>

...或更改StyleTargetType 并简单地设置TextBoxStyle 属性:

<UserControl.Resources>
    <Style TargetType="TextBox" x:Key="TextBoxBorderStyle">
        <Style.Resources>
            <Style TargetType="x:Type Border">
                <Style.Triggers>
                    <DataTrigger Binding="Binding IsReadOnly, RelativeSource=RelativeSource Mode=FindAncestor, AncestorType=TextBoxBase" Value="True">
                        <Setter Property="Opacity" Value="0.56"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Style.Resources>
    </Style>
</UserControl.Resources>

用法:

<TextBox Text="Binding MyText"
         IsReadOnly="Binding ReadOnly"
         VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled"
         Style="StaticResource TextBoxBorderStyle" />

【讨论】:

谢谢。很简单。仍然奇怪为什么我这样做的方式在设计和运行时表现不同。虽然我现在还发现我们的应用程序在运行时动态加载了一个 3rd 方主题,它没有在设计器中加载,所以它在设计时使用默认样式和模板,在运行时使用 3r 方主题(它有模板中没有 Border 子元素,所以触发器没有效果 - 所以我设置了另一个属性/对象)【参考方案2】:

替换

    <TextBox Text="Binding MyText"
             IsReadOnly="Binding ReadOnly"
             VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Disabled" >
        <TextBox.Resources>
            <StaticResource ResourceKey="TextBoxBorderStyle" />
        </TextBox.Resources>
    </TextBox>

    <TextBox Text="Binding MyText"
             IsReadOnly="Binding ReadOnly"
             VerticalScrollBarVisibility="Disabled" 
             HorizontalScrollBarVisibility="Disabled"
             Style=DynamicResource TextBoxBorderStyle/>

这应该可以解决问题。如果没有,请尝试通过删除旧样式并通过转到该文本框并右键单击 - 编辑样式/模板 - 编辑副本来创建新样式来重置您的资源字典 然后选择“资源字典”并选择你的资源字典

【讨论】:

谢谢,但样式适用于 TextBox 内边框。不适用于整个 TextBox,因此这将给出“'Border' TargetType does not match type of element 'TextBox'”。我不确定您所说的“删除旧样式并制作新样式”是什么意思,因为我既不是源自也不是指任何自定义主题或样式。也许我忘了提到样式是在自定义控件的根中定义的。 您的意思是创建并使用带有附加触发器的默认 ControlTemplate 的副本以启用 ReadOnly 的边框样式?它可能是一个选项,但它会完全覆盖当前的 ControlTemplate,如果使用另一个基本主题或样式,它可能会改变。 我的意思是为整个文本框制作一个样式。这并不难 - 你可以为那部分使用触发器 我知道。只是默认模板调整了边框的属性,而不是文本框的属性,我希望它看起来一样。 (但是我现在发现在运行时使用了不同的模板,因此我需要以某种方式为此提取 xaml 以添加已定义触发器的副本以禁用作为只读触发器的新触发器)

以上是关于WPF:InvalidCastException:无法将“System.Windows.Style”类型的对象转换为“System.Windows.ResourceDictionary”类型的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin 形式:System.InvalidCastException:'指定的转换无效

Xamarin 形式:System.InvalidCastException:“指定的强制转换无效。”

C# 转换枚举 InvalidCastException 错误

在 Unity 中使用泛型... InvalidCastException

SQL Server (ORM) 从数据库中选择数据 - System.InvalidCastException

转换为 OrganizationServiceContext 时出现 InvalidCastException