web-dev-qa-db-ja.com

ReSharper WPFエラー:「不明なDataContextのため、シンボル「MyVariable」を解決できません」

Visual Studio 2012でWPF + XAML + MVVMを使用すると、このエラーが発生します。

DataContextが不明なため、シンボル「MyVariable」を解決できません

解決策は何ですか?

31
Contango

このエラーは、WPF用のXAMLを設計するときにReSharperによって生成され、XAMLがランタイムバインディングを含むクラスを見つけることができないことを示します。これは通常、DataContextが正しく設定されていないことを示しています。

このエラーは次のことを意味します。

  • XAMLのIntellisenseは、設計時には機能しません。
  • XAMLのbindingをCtrlキーを押しながらクリックして、設計時にXAMLからC#クラスに自動的に移動することはできません。
  • プロパティで[使用状況の検索]を選択すると、XAMLおよびC#で使用状況が表示されません。
  • デザイナーは、カスタムC#クラスのライブデータを表示できません。

MVVMで考える人にとって、このエラーは、ビューがViewModelを見つけられないことを示しています。

解決策1

DataBindingの仕組みを理解するために、ある種のWebチュートリアルをご覧ください。推奨 Microsoftデータバインディングの概要

解決策2

ReSharperを使用している場合、問題のDataContextでAlt-Enterを押すと、XAMLに正しいDataContextを挿入するのに役立つメニューが表示されます。

これを使用して、問題を正しく解決しました。

enter image description here

解決策3

Visual Studioの[プロパティ]ペインで、選択したコントロールのデータコンテキストを選択できます。

enter image description here

解決策4

Blendは、データコンテキストの設定にも使用できます。 Blendで.slnファイルを開き、設計要素を選択し、プロパティで「新規」を選択します。

enter image description here

解決策5

DevExpressは、ウィザードを使用して、XAMLでこのエラーを解決することもできます。

XAMLで、データコンテキストを設定する親要素(通常はフォーム全体)を選択し、デザイナーでアクションの三角形を選択します。

次に、C#コードでクラスを参照します。

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

バインドエラーが発生するたびにメッセージボックスをポップアップ表示する 起動時のコードのスニペット を追加できます。これは非常に有用であることが判明しました。

前述のWebリンクがダウンした場合のコードは次のとおりです。

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番目のターゲットアイコンをクリックして、実行中のアプリの上にドラッグします。
  2. Ctrl + Shiftを押したままにします。
  3. 実行中のアプリの上にマウスを移動すると、マウスの下にあるコントロールの輪郭が赤で表示されます。
  4. マウスを放すと、SnoopはビジュアルツリーにすべてのXAMLを表示するウィンドウをポップアップ表示します。

enter image description here

enter image description here

ヒント9-設計時のDataContext

実際には、design timerun timeの2つの完全に独立したDataContextがあります。

これまでのソリューションのほとんどは、run time DataContextの設定に焦点を合わせていました。

design time DataContextを設定すると、Visual StudioまたはBlendのXAMLプレビューに、カスタム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プレビューでライブデータを確認できます。前述のリンクは、これがどのように機能するかをデモします(XAML設計時のライブティッククロックのYouTubeビデオで完了します!)。

言うまでもなく、この手法はMVVMパターン、およびMVVM + Dependency Injectionでも完全に機能します。 MVVMになじみのない人にとっては、MVVMは、エレガントで、クリーンで、保守しやすく、変更しやすいプロジェクトを作成するための優れた方法です。 Microsoft Blend自体は、MVVMパターンを使用して完全に記述されています。

95
Contango