ReSharper WPF error: "Не удается разрешить символ"MyVariable"из-за неизвестного DataContext"

Я испытываю эту ошибку при использовании WPF + XAML + MVVM в Visual Studio 2012.

Не удается разрешить символ "MyVariable" из-за неизвестного DataContext

Каково решение?

1 ответ

Решение

Эта ошибка генерируется ReSharper при разработке XAML для WPF и указывает, что XAML не может найти класс, который содержит привязки времени выполнения. Это обычно означает, что DataContext не установлен должным образом.

Эта ошибка означает, что:

  • Intellisense для XAML не работает так же хорошо во время разработки;
  • Невозможно автоматически перейти от XAML к классу C# во время разработки, используя Ctrl-Click на binding в XAML;
  • Когда мы выбираем "Find Usages" для свойства, оно не вызывает использования в XAML, а также в C#;
  • Дизайнер не может не отображать живые данные из пользовательского класса C#.

Для тех из нас, кто думает в MVVM, эта ошибка означает, что View не может найти ViewModel.

Решение 1

Пройдите какое-то веб-руководство, чтобы понять, как работает DataBinding. Рекомендовать обзор привязки данных Microsoft.

Решение 2

При использовании ReSharper нажатие Alt-Enter на нарушающем DataContext вызовет меню, которое поможет вам вставить правильный DataContext в ваш XAML.

Я использовал это, чтобы правильно решить проблему.

Решение 3

На панели "Свойства" Visual Studio вы можете выбрать контекст данных для выбранного элемента управления:

Решение 4

Смесь также может быть использована для установки контекста данных. Откройте файл.sln в Blend, выберите элемент дизайна, затем в свойствах выберите "New":

Решение 5

DevExpress также может помочь устранить эту ошибку в XAML для вас, используя свой мастер.

В XAML выберите родительский элемент, для которого вы хотите установить контекст данных (обычно всю форму), затем в конструкторе выберите треугольник действия.

Затем перейдите к классу с кодом C#.

Подсказка: класс будет невидимым, если вы не добавите в него конструктор без параметров.

XAML перед

<UserControl x:Class="DemoAllocation.MyActualView"
         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" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">

XAML после

<UserControl
         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:Implementation="clr-namespace:DemoAllocation.ViewModel.Implementation" x:Class="DemoAllocation.MyActualView" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
    <Implementation:MyActualViewModel/>
</UserControl.DataContext>

Подсказка 6

Если вы не видите смарт-теги в конструкторе WPF, убедитесь, что они не были отключены в определенный момент:

Решение 7

При запуске можно добавить фрагмент кода, который выдает окно сообщения каждый раз, когда возникает ошибка привязки. Это оказалось очень полезным.

В случае, если вышеупомянутая веб-ссылка не работает, вот код:

public partial class Window1 : Window
{
  public Window1()
  {
    BindingErrorTraceListener.SetTrace();
    InitializeComponent();
  }
}

Метод:

using System.Diagnostics;
using System.Text;
using System.Windows;

namespace SOTC_BindingErrorTracer
{
  public class BindingErrorTraceListener : DefaultTraceListener
  {
    private static BindingErrorTraceListener _Listener;

    public static void SetTrace()
    { SetTrace(SourceLevels.Error, TraceOptions.None); }

    public static void SetTrace(SourceLevels level, TraceOptions options)
    {
      if (_Listener == null)
      {
        _Listener = new BindingErrorTraceListener();
        PresentationTraceSources.DataBindingSource.Listeners.Add(_Listener);
      }

      _Listener.TraceOutputOptions = options;
      PresentationTraceSources.DataBindingSource.Switch.Level = level;
    }

    public static void CloseTrace()
    {
      if (_Listener == null)
      { return; }

      _Listener.Flush();
      _Listener.Close();
      PresentationTraceSources.DataBindingSource.Listeners.Remove(_Listener);
      _Listener = null;
    }



    private StringBuilder _Message = new StringBuilder();

    private BindingErrorTraceListener()
    { }

    public override void Write(string message)
    { _Message.Append(message); }

    public override void WriteLine(string message)
    {
      _Message.Append(message);

      var final = _Message.ToString();
      _Message.Length = 0;

      MessageBox.Show(final, "Binding Error", MessageBoxButton.OK, 
        MessageBoxImage.Error);
    }
  }
}

Решение 8

Воспользуйтесь бесплатной утилитой Snoop.

Есть действительно хорошая функция, которая позволяет фильтровать элементы управления с ошибками привязки. Это позволяет вам перейти прямо к визуалу с ошибкой привязки.

После запуска Snoop:

  1. Нажмите и перетащите второй целевой значок поверх запущенного приложения.
  2. Удерживайте Ctrl + Shift.
  3. Когда вы наводите указатель мыши на работающее приложение, любой элемент управления, находящийся под мышью, будет выделен красным цветом.
  4. Отпустите кнопку мыши, и Snoop отобразит окно, отображающее весь XAML в визуальном дереве.

Подсказка 9 - Время проектирования DataContext

На самом деле есть два совершенно разных DataContexts: design time а также run time,

Большинство предыдущих решений были направлены на run time DataContext.

Как только вы установите design time DataContext, предварительный просмотр XAML в Visual Studio или Blend покажет пользовательские данные, предоставленные вашим пользовательским классом C#.

При использовании Blend эти пользовательские данные также можно прочитать из файла XML, но я предпочитаю предоставлять их из своего собственного класса C#.

Чтобы установить design time DataContext, см.:

Или добавьте это к любому элементу (это будет новый класс MyClass во время разработки, так что Intellisense будет работать):

d:DataContext="{d:DesignInstance d:Type=viewModel:MyClass, IsDesignTimeCreatable=True}"

И это в шапку:

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"

За кулисами, когда вы устанавливаете design time DataContext:

  • Дизайнер Visual Studio (или Blend) автоматически создаст новый экземпляр класса, на который вы указываете. Это также работает, если вы создаете статический класс.
  • Затем в предварительном просмотре XAML, когда вы редактируете XAML, он будет отображать живые данные из вашего класса C#.
  • Это делает проектирование действительно быстрым, поскольку вы можете работать с оперативными данными во время разработки, и вам не нужно постоянно запускать программу, чтобы увидеть, как она выглядит.

Обратите внимание, что предварительный просмотр XAML отображается только при использовании пользовательского элемента управления. Если вы предпочитаете использовать DataTemplates, нет проблем: вы можете создать временный пользовательский элемент управления, который включает в себя DataTemplate, и установить design time DataContext для указания на статический класс. Кодируйте статический класс так, чтобы он создавал новый экземпляр вашей ViewModel (то есть класс, с которым вы хотите связать). Например, ваш статический класс может считывать данные из базы данных, заполнять свойства ViewModel, и вы можете работать с живыми данными из базы данных во время разработки XAML.

Этот метод также прекрасно работает с инъекцией зависимостей, такой как Unity или MEF. Вы должны указать свой design time DataContext в статическом классе, который извлекает соответствующие классы из контейнера внедрения зависимостей и все настраивает. После этого вы можете увидеть живые данные во время разработки в предварительном просмотре XAML. Вышеупомянутые ссылки демонстрируют, как это работает (в комплекте с видео на YouTube с часами в реальном времени во время разработки XAML!).

Излишне говорить, что этот метод отлично работает с паттерном MVVM, а также с MVVM + Dependency Injection. Для тех из вас, кто не знаком с MVVM, это отличный способ создавать элегантные, чистые, легко обслуживаемые и легко изменяемые проекты. Сама Microsoft Blend полностью написана с использованием шаблона MVVM.

Другие вопросы по тегам