2016-12-14 50 views
4

我一直在困扰着我一段时间,但我相信我终于找到了它。症状是当我的一个绑定属性触发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的例子:enter image description here。你可以看到大插槽是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等。

+0

我很好奇,如果有能见度结合将是有效的两个'ItemsControl'。即使控件不可见,是否还有额外的处理开销? – Lunyx

+1

更改'ContentTemplate'是一个可靠的解决方案,不应该导致'ArgumentNullException'本身。问题可能来自您的控件'CompactCustomEntityControl'和'FullCustomEntityControl'。 [启用抛出的CLR异常](https://msdn.microsoft.com/en-us/library/x85tt0dd.aspx),你可以得到在VS调试中抛出异常的实际位置。 –

+0

我试着用简化的例子重新创建了你的问题(删除了你的自定义控件,CollectionViewSource等等),并且一切似乎都奏效了 - 它确实用我的TextBlock模板切换了我的TextBox模板......我建议你试着创建简单的例子,并从那里添加缺失的部分,直到找到真正的根本原因 –

回答

1

每个ItemsControl都有ItemTemplateSelector属性,你可以借此帮忙。

+0

据我所知,'ItemTemplateSelector'只执行一次选择。在我的示例中,模板在绑定变量更改时得到更新。 – Lunyx

1

我不知道,我是否理解错误的问题,但是当我将代码复制到我的解决方案时,它完美地工作。下面是我的变化,

有一件事我所做的就是,用路径= DataContext.ShowCompactView替换路径= ViewModel.ShowCompactView和RelativeSource是我的主窗口,

<ItemsControl Background="Transparent" 
      ItemsSource="{Binding Source={StaticResource SomeCollectionView}}"> 
     <ItemsControl.Resources> 
      <DataTemplate x:Key="FullViewTemplate"> 
       <Border > 
        <Label Content="{Binding}" 
               /> 
       </Border> 
      </DataTemplate> 
      <DataTemplate x:Key="CompactViewTemplate"> 
       <Border > 
        <Button Content="{Binding}" 
               /> 
       </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=Window}, Path=DataContext.ShowCompactView}" Value="True"> 
            <Setter Property="ContentTemplate" Value="{StaticResource CompactViewTemplate}"/> 
           </DataTrigger> 
          </Style.Triggers> 
         </Style> 
        </ContentControl.Style> 
       </ContentControl> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
+0

我现有的代码已经工作;然而,在我提到的情况中,有一些情况出现,而不是完全呈现控件,它只有控件所在的空白空间。 – Lunyx

1

我您的设置,一切都取得了quick project似乎工作。错误似乎与在与PresentationCore交互的CompactCustomEntityControl/FullCustomEntityControl中完成的某些操作有关。

尝试启用.NET Framework的源在调试 - >选项步进,看看发生了什么事情:

setup screenshot

+0

设置所有这些选项,使用Microsoft Symbol服务器,仍然没有可用的源。不知道在框架内进行调试有多大的帮助。 – Lunyx

+0

@Lunyx尝试在Options-> Debugging-> Symbols中关闭默认的'Microsoft Symbol Servers',将https://referencesource.microsoft.com/symbols添加为源代码。打开.net框架调试可能有点麻烦,因为经常mscorlib版本不匹配'微软Symbol服务器'的源代码版本,但我认为在你的情况下可以帮助 - 你应该看到引发的确切代码。根据我的经验,这通常可以解决复杂的WPF问题 – Shorstok

+0

@Lunyx设置源服务器,如[这里](http://i.imgur.com/wnMJoLV.jpg) – Shorstok