我一直在困扰着我一段时间,但我相信我终于找到了它。症状是当我的一个绑定属性触发DataTrigger
时,我的WPF控件无法正确呈现,即将ContentTemplate
换掉。堆栈跟踪:如何根据绑定属性动态更改ContentTemplate?
System.ArgumentNullException: Value cannot be null.
Parameter name: d
at MS.Internal.Data.ElementObjectRef.GetObject(DependencyObject d, ObjectRefArgs args)
at MS.Internal.Data.ObjectRef.GetDataObject(DependencyObject d, ObjectRefArgs args)
at System.Windows.Data.BindingExpression.MS.Internal.Data.IDataBindEngineClient.VerifySourceReference(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Task.Run(Boolean lastChance)
at MS.Internal.Data.DataBindEngine.Run(Object arg)
at MS.Internal.Data.DataBindEngine.OnLayoutUpdated(Object sender, EventArgs e)
at System.Windows.ContextLayoutManager.fireLayoutUpdateEvent()
at System.Windows.ContextLayoutManager.UpdateLayout()
at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
at System.Windows.Media.MediaContext.InvokeOnRenderCallback.DoWork()
at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
调试器不会在所有帮助,因为它只是打破上application.Run()
。下面是我在实际的XAML方面正在做的:
<CollectionViewSource x:Key="SomeCollectionView"
Source="{Binding StatsByUser}"
IsLiveSortingRequested="True">
<CollectionViewSource.SortDescriptions>
<scm:SortDescription PropertyName="Amount" Direction="Descending"/>
<scm:SortDescription PropertyName="Name" Direction="Ascending"/>
</CollectionViewSource.SortDescriptions>
</CollectionViewSource>
<ItemsControl Background="Transparent" Width="{StaticResource Width}"
ItemsSource="{Binding Source={StaticResource SomeCollectionView}}">
<ItemsControl.Resources>
<DataTemplate x:Key="FullViewTemplate">
<Border Style="{StaticResource BorderStyle}">
<controls:FullCustomEntityControl CustomEntityObject="{Binding}"
Style="{StaticResource PanelStyle}"
MouseDown="Info_OnMouseDown"/>
</Border>
</DataTemplate>
<DataTemplate x:Key="CompactViewTemplate">
<Border Style="{StaticResource BorderStyle}">
<controls:CompactCustomEntityControl CustomEntityObject="{Binding}"
Style="{StaticResource PanelStyle}"
MouseDown="Info_OnMouseDown"/>
</Border>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentControl Content="{Binding}">
<ContentControl.Style>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="ContentTemplate" Value="{StaticResource FullViewTemplate}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType=c:ShellView}, Path=ViewModel.ShowCompactView}" Value="True">
<Setter Property="ContentTemplate" Value="{StaticResource CompactViewTemplate}"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
每当ViewModel.ShowCompactView
引发PropertyChanged
事件,并揭开序幕DataTrigger
,它会将ContentTemplate
,然后抛出这个错误。有没有办法解决这个问题或更好的方法来构建ContentTemplate
交换,这不会导致这种情况?
编辑:潜在的相关支持文章https://support.microsoft.com/en-us/kb/2461678
EDIT2:发生了什么ui的例子:。你可以看到大插槽是FullCustomEntityControl
,小插槽是CompactCustomEntityControl
。将它们保留在任何一种模式而不改变它都不会导致任何问题,但让数据触发器改变它们会导致类似的问题。此外,所使用的控制应该是一致的,而不是看起来像在这里分裂。通过将它们留在任何一种模式下,我的意思是删除数据触发器并选择其中一个。
EDIT3:一个类似的问题发帖与微软的人回答:https://social.msdn.microsoft.com/Forums/vstudio/en-US/fb4d0f41-bfea-409f-b8ac-e66558984b7a/argumentnullexception-when-displaying-wpf-window?forum=wpf
相关信息:
如果你在堆栈上得到一个ArgumentNullException与VerifySourceReference,它肯定所致连接561752中描述的问题。即使您的应用程序没有直接使用ElementName绑定,它也可能间接使用它们 - 几个内置控件使用ElementName绑定:ComboBox,ContextMenu,MenuItem等。
我很好奇,如果有能见度结合将是有效的两个'ItemsControl'。即使控件不可见,是否还有额外的处理开销? – Lunyx
更改'ContentTemplate'是一个可靠的解决方案,不应该导致'ArgumentNullException'本身。问题可能来自您的控件'CompactCustomEntityControl'和'FullCustomEntityControl'。 [启用抛出的CLR异常](https://msdn.microsoft.com/en-us/library/x85tt0dd.aspx),你可以得到在VS调试中抛出异常的实际位置。 –
我试着用简化的例子重新创建了你的问题(删除了你的自定义控件,CollectionViewSource等等),并且一切似乎都奏效了 - 它确实用我的TextBlock模板切换了我的TextBox模板......我建议你试着创建简单的例子,并从那里添加缺失的部分,直到找到真正的根本原因 –