Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

Решение 1

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

Решение 2

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

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

enter image description here

Решение 3

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

enter image description here

Решение 4

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

enter image description here

Решение 5

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

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

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

enter image description here

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

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, убедитесь, что они не были отключены в какой-то момент:

enter image description here

Решение 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:

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

enter image description here

enter image description here

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

На самом деле есть два полностью отдельных DataContexts: design time и run time.

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

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

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

Чтобы установить 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, он отображает текущие данные из вашего класса С#.
  • Это делает проектирование очень быстрым, так как вы можете работать с живыми данными во время разработки, и вам не нужно постоянно запускать программу, чтобы посмотреть, как она выглядит.

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

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

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