1

MainWindow.xaml にこれを含む WPF アプリケーション (exe) があるとします。

<Grid>
    <extraControls:MyMVVMUserControl MyDependencyProperty="{Binding Something}"/>
    <extraControls:MyUserControl MyDependencyProperty="{Binding Something}" />
</Grid>

私の MainWindow.xaml.cs は次のようになります。

public MainWindow()
{
    DataContext = new MainWindowVM();
    InitializeComponent();
}

そして、私の MainWindowVM.cs には、プロパティSomethingが変更されたことを通知するためのプロパティ設定があります。

ユーザー コントロールは、別の dll で作成されます。ご想像のとおりMyMVVMUserControl、DataContext がビュー モデルに設定されています。

public MyMVVMUserControl()
{
    DataContext = new MyMVVMUserControlVM();
    InitializeComponent();
}

MyUserControlコード ビハインドに DataContext が設定されていません。

興味深いことに、両者MyDependencyPropertyのセットアップはまったく同じです。

ただし、MVVM バージョンは機能しません。

少し掘り下げた後、MainWindow.xaml では、(MainWindow.cs に設定された (MainWindowVM に設定された) DataContext ではなく) DataContext として MyMVVMUserControl のビュー モデル設定が使用{Binding Something}れていることがわかりました。

そして私の質問はなぜですか?

WPF がユーザー コントロールの内部を調べて、実際のアプリケーションにあるバインドにその DataContext を使用するのはなぜですか?

(注:バインディングにソースを設定することでこれを回避できることはわかっていますが、他のユーザーが私のユーザーコントロールを使用できるようにしたいと考えています。しかし、この問題により、必要な人のために組み込みの「落とし穴」ができましたユーザーコントロールを使用するために。)

4

2 に答える 2

1

内からDataContexta のを設定するべきではありません。これにより、別の UI レイヤーとデータ レイヤーを持つという WPF の最大の利点の 1 つが無効になります。UserControlUserControlDataContextUserControl

が他に設定されていないDataContext場合、WPF オブジェクトは親オブジェクトからのみ継承します。DataContextが作成されているとき、を新しいにMyMVVMUserControl設定しているため、が から継承されるのを防ぎます。DataContextMyMVVMUserControlVMDataContextMainWindow

したがって、 UserControl のコンストラクターで明示的に設定するため、に設定するMVVMUserControlのが通常です。DataContextMyMVVMUserControlVM

これは仕様によるものです。WPF/MVVM の UI オブジェクトは、データ レイヤーの視覚的表現のみを意図しているため、データ レイヤーを設定してから、データ レイヤーにないものにプロパティをバインドしようとしてもあまり意味がありません。

たとえば、次のコード行を見てください。

 <UserControl DataContext="{Binding ClassA}" Content="{Binding Name}" />

Contentこれにより、プロパティが にバインドされます。UserControl.DataContext.NameこれはClassA.Nameです。バインディングは親の ではなく、UserControl.Parent.DataContext.Name現在のオブジェクトの を参照する必要があるため、これが へのバインディングになる場合はあまり意味がありません。DataContextDataContext

したがって、 a の をそれ自体の内部から設定するDataContextのは、 がアプリケーションの残りの部分からのデータと対話することを意図していない独自の個別のオブジェクトである場合UserControlだけです。これまでにないこと:)UserControlUserControl

通常、私UserControlsはほとんどの場合、次の2つのいずれかです。

  • ViewModel(またはModel)の視覚的表現( CustomerUserControlfor aなど)。この場合、慣れたときに必要なCustomerViewModelものを渡します。DataContext

    例えば、

    <local:CustomerUserControl DataContext="{Binding SelectedCustomer}" />
    

    また

    <DataTemplate DataType="{x:Type local:CustomerModel}">
        <local:CustomerUserControl />
    </DataTemplate>
    
  • または、 custom を介して必要な外部データを受け取りDependencyProperties、依存関係プロパティDatePickerを持つコントロールや、およびSelectedDateCalculatorUserControlEquationValue

    <local:DatePickerUserControl SelectedDate="{Binding SomeDate}" />
    
    <local:CalculatorUserControl Equation="{Binding SomeString}" 
                                 Value="{Binding SomeDouble}" />
    

あなたの場合、最初のケースを使用する必要があり、必要なデータを含むにaViewModelを渡す必要があるように聞こえます。UserControl

<extraControls:MyMVVMUserControl DataContext="{Binding MyMVVMUserControlVM}"
                                 MyDependencyProperty="{Binding Something}">

また

<extraControls:MyMVVMUserControl MyDependencyProperty="{Binding Something}">
    <extraControls:MyMVVMUserControl.DataContext>
        <viewModels:MyMVVMUserControlVM />
    </extraControls:MyMVVMUserControl.DataContext>
<extraControls:MyMVVMUserControl />
于 2013-02-07T20:21:46.790 に答える