Изменение привязки ContentControl приводит к нулевому DataContext - PullRequest
0 голосов
/ 19 марта 2020

Возможно, один из вас мог бы просветить меня по следующей проблеме. Я использую окно списка как способ навигации между двумя моделями представления.

<Window x:Class="MyWPFApp.ShellView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:cal="http://www.caliburnproject.org">

  <Grid Background="White">
     <Grid.ColumnDefinitions>
        <ColumnDefinition Width="2*"/>
        <ColumnDefinition Width="8*"/>
     </Grid.ColumnDefinitions>
     <ListBox Grid.Column="0" cal:Message.Attach="[Event SelectionChanged] 
= [Action onViewSelectionChange($this.SelectedItem.Text)]">
        <TextBlock Text="FirstView"/>
        <TextBlock Text="SecondView"/>
     </ListBox>
        <ContentControl Grid.Column="1" Content="{Binding MyViewModel}"/>
  </Grid>

namespace MyWPFApp
{
    public class ShellViewModel : Caliburn.Micro.PropertyChangedBase, IShell
   {
      private object _vm;

      public object MyViewModel
      {
         get { return _vm; }
         set { _vm = value; NotifyOfPropertyChange(() => MyViewModel); }
      }

      public FirstViewModel vm1;
      public SecondViewModel vm2;



      public ShellViewModel()
      {
         vm1 = new FirstViewModel();
         vm2 = new SecondViewModel();
         MyViewModel = vm1;

      }

      public void onViewSelectionChange(string str)
      {

         switch (str)
         {
            case "FirstView":
               MyViewModel = vm1;
               break;
            case "SecondView":
               MyViewModel = vm2;
               break;
            default:
               break;

         }
      }
   }
}

Я создал 2 матрицы данных, чтобы связать модель представления с ее видом

<Application x:Class="MyWPFApp.App"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:local="clr-MyWPFApp">
  <Application.Resources>
  <ResourceDictionary>
     <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary>
           <local:AppBootstrapper x:Key="bootstrapper" />
        </ResourceDictionary>
     </ResourceDictionary.MergedDictionaries>
     <DataTemplate DataType="{x:Type local:FirstViewModel}">
        <Grid>
           <local:FirstView></local:FirstView>
        </Grid>
     </DataTemplate>
     <DataTemplate DataType="{x:Type local:SecondViewModel}">
        <Grid>
           <local:SecondView></local:SecondView>
        </Grid>
     </DataTemplate>
  </ResourceDictionary>
  </Application.Resources>
  </Application>

FirstView действительно имеет элементы управления, которые имеют привязки к свойствам в FirstViewModel

   <UserControl x:Class="MyWPFApp.FirstView"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
            xmlns:local="clr-namespace:MyWPFApp"
            xmlns:cal="http://www.caliburnproject.org"
            mc:Ignorable="d" 
            d:DesignHeight="300" d:DesignWidth="300">
  <Grid Background="Aquamarine">
     <ListBox SelectedIndex="{Binding SelectedIndex}" 
              SelectedItem="{Binding SelectedItem}"
              cal:Message.Attach="[Event SelectionChanged]=[Action OnLBSelectionChanged($source)]">
        <ListBoxItem>apple</ListBoxItem>
        <ListBoxItem>orange</ListBoxItem>
        <ListBoxItem>pear</ListBoxItem>
     </ListBox>
  </Grid>

using Caliburn.Micro;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MyWPFApp
{
   public class FirstViewModel : PropertyChangedBase
   {

      private int _selectedindex;

      public int SelectedIndex
      {
         get { return _selectedindex; }
         set { _selectedindex = value; NotifyOfPropertyChange(() => SelectedIndex); }
      }


      private string _selecteditem;

      public string SelectedItem
      {
         get { return _selecteditem; }
         set { _selecteditem = value; NotifyOfPropertyChange(() => SelectedItem); }
      }



      public FirstViewModel()
      {
      }


      public void OnLBSelectionChanged(System.Windows.Controls.ListBox lb)
      {
         if(lb.DataContext == null)
         {
            Debug.WriteLine("The DataContext is null");
         }

      }

   }
}

SecondView не содержит элементов управления.

Когда ShellView изменение выбора списка из FirstView в SecondView, я заметил, что FirstView ListBox DataContext становится нулевым.

  public void OnLBSelectionChanged(System.Windows.Controls.ListBox lb)
  {
     if(lb.DataContext == null)
     {
        Debug.WriteLine("The DataContext is null");
     }

  }

Я бы предпочел не обрабатывать изменения выбора в поисках нулевого DataContext. Вместо этого я хотел бы знать, что на самом деле происходит. Спасибо.

1 Ответ

1 голос
/ 19 марта 2020

Причина, по которой это происходит, заключается в том, что DataContext для FirstView неявно подключается WPF, когда для свойства ContentControl 'Content установлено значение FirstViewModel посредством привязки данных.

Как только привязка изменится на SecondViewModel, FirstViewModel выйдет из области видимости, и, таким образом, WPF уберет за собой, удалив FirstViewModel, FirstView и его неявную привязку DataContext.

Надеюсь, это поможет.

...