使用StaticResource加载WPF自定义控件时触发InvalidCastException异常
问题原因与解决方案
你的判断完全正确,这个异常就是资源加载顺序导致的:
StaticResource是在XAML加载阶段立即解析查找资源,当解析DrawerMenu的样式时,后面定义的LBXI.DrawerMenu样式还没被WPF载入内存,此时WPF会生成一个MS.Internal.NamedObject作为临时占位符。当后续实际需要Style类型的资源时,这个占位符无法转换为System.Windows.Style,就抛出了InvalidCastException。DynamicResource是延迟到运行时实际使用资源时才去查找,这时候LBXI.DrawerMenu样式已经被加载完成,所以不会出现异常。
解决方案
方案1:调整资源定义顺序
把LBXI.DrawerMenu的样式放在DrawerMenu样式之前,确保StaticResource查找时目标资源已存在:
<!-- 先定义ItemContainerStyle需要的样式 --> <Style TargetType="{x:Type ListBoxItem}" x:Key="LBXI.DrawerMenu"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <Border BorderThickness="1" BorderBrush="Black" > <TextBox Text="{Binding .}"/> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> <!-- 再定义DrawerMenu的样式 --> <Style TargetType="{x:Type local:DrawerMenu}"> <Setter Property="ItemContainerStyle" Value="{StaticResource LBXI.DrawerMenu}"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:DrawerMenu}"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="auto"/> <RowDefinition/> </Grid.RowDefinitions> <ToggleButton Content="Open" x:Name="Icon" IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=IsOpen,Mode=TwoWay}" HorizontalAlignment="Left" Width="30" Height="30"/> <ItemsPresenter Grid.Row="1"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
方案2:继续使用DynamicResource
如果资源顺序不方便调整(比如资源分散在多个字典中),保持使用DynamicResource是可行的,虽然它比StaticResource多一点运行时开销,但大多数场景下可以忽略:
<Setter Property="ItemContainerStyle" Value="{DynamicResource LBXI.DrawerMenu}"/>
内容的提问来源于stack exchange,提问作者wu-qian-qian
相关产品推荐
相关产品推荐

