使用<样式TargetType=时无法强制转换错误
本文关键字:转换 错误 样式 TargetType 使用 | 更新日期: 2023-09-27 18:01:33
我试图使用资源字典和样式TargetType
属性来改变我的解决方案中的按钮的外观。当加载第一个按钮时,我在运行时收到cast错误。如果我在按钮的属性中手动设置样式,一切都可以正常工作,但关键是要更改所有按钮的外观,而不是一次更改一个。
下面是相关的例外:
System.Windows.Markup.XamlParseException occurred
HResult=-2146233087
Message='Initialization of 'System.Windows.Controls.Button' threw an exception.' Line number '6' and line position '72'.
Source=PresentationFramework
LineNumber=6
LinePosition=72
StackTrace:
at System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader, IXamlObjectWriterFactory writerFactory, Boolean skipJournaledProperties, Object rootObject, XamlObjectWriterSettings settings, Uri baseUri)
at System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader, Boolean skipJournaledProperties, Object rootObject, XamlAccessLevel accessLevel, Uri baseUri)
at System.Windows.Markup.XamlReader.LoadBaml(Stream stream, ParserContext parserContext, Object parent, Boolean closeStream)
at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
at WpfTestApplication.Views.MainWindow.InitializeComponent() in d:'TFSC'CUDL'Research'Chris.Dailey'WpfTestApplication'WpfTestApplication'Views'MainWindow.xaml:line 1
at WpfTestApplication.Views.MainWindow..ctor() in d:'TFSC'CUDL'Research'Chris.Dailey'WpfTestApplication'WpfTestApplication'Views'MainWindow.xaml.cs:line 28
InnerException: System.InvalidCastException
HResult=-2147467262
Message=Unable to cast object of type 'MS.Internal.NamedObject' to type 'System.Windows.FrameworkTemplate'.
Source=PresentationFramework
StackTrace:
at System.Windows.Controls.Control.OnTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.StyleHelper.ApplyStyleOrTemplateValue(FrameworkObject fo, DependencyProperty dp)
at System.Windows.StyleHelper.InvalidateContainerDependents(DependencyObject container, FrugalStructList`1& exclusionContainerDependents, FrugalStructList`1& oldContainerDependents, FrugalStructList`1& newContainerDependents)
at System.Windows.StyleHelper.DoStyleInvalidations(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle)
at System.Windows.StyleHelper.UpdateStyleCache(FrameworkElement fe, FrameworkContentElement fce, Style oldStyle, Style newStyle, Style& styleCache)
at System.Windows.FrameworkElement.OnStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
at System.Windows.DependencyObject.InvalidateProperty(DependencyProperty dp, Boolean preserveCurrentValue)
at System.Windows.FrameworkElement.UpdateStyleProperty()
at System.Windows.FrameworkElement.OnInitialized(EventArgs e)
at System.Windows.FrameworkElement.TryFireInitialized()
at System.Windows.FrameworkElement.EndInit()
at MS.Internal.Xaml.Runtime.ClrObjectRuntime.InitializationGuard(XamlType xamlType, Object obj, Boolean begin)
InnerException:
下面是相关代码。资源字典:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Style TargetType="{x:Type Button}">
<Style TargetType="{x:Type Button}">
<Setter Property="Control.Template" Value="{StaticResource ButtonTemplate}"
</Style>
<ControlTemplate x:Key="ButtonTemplate" TargetType="{x:Type Button}">
<Border Name="Border" BorderBrush="Orange" BorderThickness="3" CornerRadius="3" Background="Red" TextBlock.Foreground="White">
<Grid>
<Rectangle Name="FocusCue" Visibility="Hidden" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2" SnapsToDevicePixels="True" ></Rectangle>
<ContentPresenter RecognizesAccessKey="True" Margin="{TemplateBinding Padding}"></ContentPresenter>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="DarkRed" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background" Value="IndianRed" />
<Setter TargetName="Border" Property="BorderBrush" Value="DarkKhaki" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="FocusCue" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="TextBlock.Foreground" Value="Gray" />
<Setter TargetName="Border" Property="Background" Value="MistyRose" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</ResourceDictionary>
主窗口:
<Window x:Class="WpfTestApplication.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<WrapPanel>
<Button x:Name="ButtonGradient" Click="ButtonGradient_OnClick">Gradient</Button>
<Button x:Name="ButtonDrawing" Click="ButtonDrawing_OnClick">Drawing</Button>
<Button x:Name="ButtonEventTester" Click="ButtonEventTester_OnClick">Event Tester</Button>
<Button x:Name="ButtonCommandTester" Style="{x:Null}" Command="New">Execute a Command</Button>
</WrapPanel>
我将感谢任何可能导致这种情况的输入。外部错误是完全无用的,我对此了解得不够,无法理解为什么会发生类型转换错误。
使用VS2012和你上面的样式,我能够成功地应用你的ControlTemplate。我确实先把它包装在一个Style
中,但这更多的是一个偏好问题。
唯一的另一个区别是,我不得不猜测你为你的Border
做了什么,因为它不包括在内。
下面的样式在设计时和运行时都能完美地工作:
<Style TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="Border" Background="LightBlue">
<Grid>
<Rectangle Name="FocusCue" Visibility="Hidden" Stroke="Black" StrokeThickness="1" StrokeDashArray="1 2" SnapsToDevicePixels="True" ></Rectangle>
<ContentPresenter RecognizesAccessKey="True" Margin="{TemplateBinding Padding}"></ContentPresenter>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Background" Value="DarkRed" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Background" Value="IndianRed" />
<Setter TargetName="Border" Property="BorderBrush" Value="DarkKhaki" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="True">
<Setter TargetName="FocusCue" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Border" Property="TextBlock.Foreground" Value="Gray" />
<Setter TargetName="Border" Property="Background" Value="MistyRose" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
在Xaml代码中,顺序很重要。把你的模板放在引用它的样式的上面。
当使用WPF资源时,请记住在正确的顺序。
必须定义在其他地方引用的样式或模板才能使用。换句话说,如果Style1使用BrushA作为StaticResource,然后BrushA必须在Style1之前定义。否则,您将得到有趣的错误,如:
无法强制类型为"MS.Internal"的对象。NamedObject' to type"System.Windows.FrameworkTemplate"
我有一个类似的问题,原来我的风格是使用StaticResource而不是DynamicResource。http://blog.alner.net/archive/2010/05/07/wpf-style-and-template-resources_order-matters.aspx