2017-03-07 20 views
0

viewModelsをインスタンス化する際に問題が発生しています。MVVM ViewとViewModelのバインディングの問題

多くの場合、依存関係を注入する必要があるため、ViewModelLocatorを使用しています。しかし、ViewModelに引数を渡す必要がある場合があります。私が理解していることから、私はViweModel-Firstアプローチを使用する必要があります。つまり、実行時にビューにバインドされたViewModel用のDataTemplateを作成する必要があります。

ViewModelを作成して引数を渡すと、正しいコンストラクタが呼び出されるという問題があります。ただし、ViewModelはビューにバインドされているため、ビューはviewmodelのデフォルトのパラメータのないコンストラクタを呼び出します。ここで

は、XAMLは、ユーザーコントロールのためにどのように見えるかを私はViewModelにバインドしています:

<UserControl x:Class="MyView"> 
    <UserControl.DataContext> 
     <viewModels:MyViewModel></viewModels:MyViewModel> 
    </UserControl.DataContext> 
</UserControl> 

データテンプレートは、次のようになります。ここでは

<DataTemplate DataType="{x:Type viewModels:MyViewModel}"> 
    <views:MyView></views:MyView> 
</DataTemplate> 

は、サンプルのViewModelです:

public class MyViewModel : ViewModelBase 
{ 
    private MyModel _myModel; 

    public MyViewModel() 
    { 
    } 

    public MyViewModel(MyModel myModel) 
    { 
    _myModel = myModel; 
    } 
} 

正しいコンストラクタを使用してviewModelを作成し、arguを渡すとviewModelは、viewModelのデフォルトのパラメータのないコンストラクタを使用してビューによって再度作成されます。

誰もがこれが起こっている理由を説明し、正しく動作するようにviewmodel-firstアプローチを設定する方法を説明してもらえますか?私は犠牲になり、私はこの一日中働いています。

おかげで、 ティム

答えて

1

あなたUserControlから次のコードを削除し、私の残りの指示に従った場合、私はあなたが欲しいものを持っていると信じて:

この

<UserControl.DataContext> 
     <viewModels:MyViewModel></viewModels:MyViewModel> 
</UserControl.DataContext> 
を削除します

今、UserControlまたはWindowViewModelにバインドされていますur UserControlまたはWindow。あなたがこれを行うような方法はそうのようなResourceDictionaryで指定DataTemplateと一緒にあなたのUserControlWindowContentControlを使用することです:

の.xaml:

<Window x:Class="WPF_Sandbox.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:vm="clr-namespace:WpfApplication1.ViewModels" 
    Title="MainWindow" 
    x:Name="ThisControl"> 
    <Window.DataContext> 
     <vm:MainWindowViewModel/> 
    </Window.DataContext> 
    <DockPanel LastChildFill="True"> 
     <ContentControl DockPanel.Dock="Left" Content="{Binding NavigationRegion}"/> 
     <ContentControl DockPanel.Dock="Left" Content="{Binding ContentRegion}"/> 
    </DockPanel>  
</Window> 

ContentControlは、暗黙的にルックアップします(ResourceDictionaryオブジェクトの階層内の)DataTemplateは、ContentプロパティにバインドされているViewModelに関連付けられています。

MainWindowViewModel:だから私たちはあなたのようなMyViewModelのインスタンスにMainWindowViewModelContentRegionプロパティを設定することを言うことができます。CS

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace WpfApplication1.ViewModels 
{ 
    public class MainWindowViewModel : ViewModel 
    { 
     private object _navigationRegion; 
     private object _contentRegion; 

     public object NavigationRegion 
     { 
      get 
      { 
       return _navigationRegion; 
      } 
      set 
      { 
       _navigationRegion = value; 
       OnPropertyChanged(nameof(NavigationRegion)); 
      } 
     } 

     public object ContentRegion 
     { 
      get 
      { 
       return _contentRegion; 
      } 
      set 
      { 
       _contentRegion = value; 
       OnPropertyChanged(nameof(ContentRegion)); 
      } 
     } 

     public MainWindowViewModel() 
     { 
      ContentRegion = new MyViewModel(new MyModel()); 
     } 
    } 
} 

そして、あなたがそうのように指定ResourceDictionaryを持っている:

MyResourceDictionary.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:local="clr-namespace:WpfApplication1" 
        xmlns:vm="clr-namespace:WpfApplication1.ViewModels" 
        xmlns:views="clr-namespace:WpfApplication1.Views"> 
    <DataTemplate DataType="{x:Type vm:MyViewModel}"> 
     <views:MyView/> 
    </DataTemplate> 

</ResourceDictionary> 

そして、あなたはあなたのようなApp.xamlファイルであなたのApplication.ResourcesであなたのResourceDictionaryを合併していますso:

<Application x:Class="WpfApplication1.App" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:local="clr-namespace:WpfApplication1" 
      StartupUri="MainWindow.xaml"> 
    <Application.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="MyResourceDictionary.xaml"/> 
      </ResourceDictionary.MergedDictionaries> 
     </ResourceDictionary> 
    </Application.Resources> 
</Application> 

フレームワークは、データ型MyViewModelに対して暗黙的にDataTemplateを探します。フレームワークでは、指定したResourceDictionaryMyViewModelDataTemplateが見つかり、MyViewユーザコントロールで表されることがわかります。この時点で、フレームワークはMyViewのユーザーコントロールをレンダリングします。

そして後世のために:

ViewModel.cs

using System.ComponentModel; 

namespace WpfApplication1.ViewModels 
{ 
    public abstract class ViewModel : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected string _title; 

     protected string Title 
     { 
      get 
      { 
       return _title; 
      } 
      set 
      { 
       _title = value; 
       OnPropertyChanged(nameof(Title)); 
      } 
     } 

     protected void OnPropertyChanged(string propName) 
     { 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); 
     } 
    } 
} 
+1

私は助けることができるようにいくつかのコードを表示してください。あなたのコメントだけでは何の問題なのかははっきりしない。 – user1286901

+0

私は混乱のために謝罪します。私は本当にオフィスから投稿することはできません。それはロックされています。基本的に私の質問に答えました。そこに2つの問題があった。最初に、ロケータがビューモデルをインスタンス化するために使用されたため、ロケータを使用してビュー内のコンテキストをバインドし、再びviemodelを呼び出しました。 2番目の問題は、コンテンツコントロールに返されて表示されていたユーザーコントロールのデータコンテキストを定義することでした。したがって、コントロールとコードの両方によって呼び出されました。再度、感謝します。 – user953710

関連する問題