2016-12-14 51 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