How to dynamically change ContentTemplate based on bound property?

I had a problem that bothered me for a while, but I believe that I’m finally tracking it. The symptoms are that my WPF controls will not display correctly if one of my related properties calls DataTrigger, which swaps ContentTemplate. Stack trace:

  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)

The debugger does not help at all, since it just breaks into application.Run(). Here is what I do in terms of actual haml:

  <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>

Whenever it ViewModel.ShowCompactViewraises an event PropertyChangedand discards DataTrigger, it toggles ContentTemplate, which then throws this error. Is there a way to fix this or the best way to archive a swap ContentTemplatethat won't lead to this?

: https://support.microsoft.com/en-us/kb/2461678

Edit2: , : enter image description here. , - FullCustomEntityControl, - CompactCustomEntityControl. , - , . , , , . , .

Edit3: - Microsoft : https://social.msdn.microsoft.com/Forums/vstudio/en-US/fb4d0f41-bfea-409f-b8ac-e66558984b7a/argumentnullexception-when-displaying-wpf-window?forum=wpf

:

ArgumentNullException VerifySourceReference , , Connect 561752. ElementName , - ElementName: ComboBox, ContextMenu, MenuItem ..

+4
3

ItemsControl ItemTemplateSelector, .

+1

, , , . ,

, , - " " = "ViewModel.ShowCompactView" Path = DataContext.ShowCompactView, - MainWindow,

<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>
+1

, , , . , , -, CompactCustomEntityControl/FullCustomEntityControl PresentationCore.

.NET Framework Debug- > Options, , :

installation screenshot

+1

Source: https://habr.com/ru/post/1663698/


All Articles