2017-10-27 20 views
0

私はC#とWPFの新機能で、必要な場所でデータを取得するのに少し苦労しています。WPF/C#親ビューからカスタムコントロールにViewModelを割り当てる

私は1つのマスターデータセットを持っています。これらのデータセットは、それぞれ独自のViewModelを持つさまざまなユーザーコントロールと共有する必要があります。問題は、親XAMLのコントロールにViewModelを割り当てて、カスタムコントロールのXAMLからそのViewModelにアクセスできるようには見えないことです。

コントロールをViewModelにバインドしますが、コントロール内のdatacontextはxaml内のそのモデルにアクセスできません。または、ユーザーコントロールでdatacontextを設定してviewmodelにアクセスできるようにしますバインディングは親ではなくローカルのdatacontextを参照しているため、xamlのviewmodelにバインドできません。

これは間違っているかもしれませんが、私が見たほとんどの例は、カスタムコントロールxamlでViewModelをインスタンス化するようですが、ViewModelをどのように取得して正しいDataModelデータモデルの一部)。

私がやろうとしていることを次のように説明してください。

は、まず私がMainViewModel.cs

namespace BindingTest1 
{ 
    class MainViewModel 
    { 
     private MyViewModel _myFirstViewModel; 
     public MyViewModel MyFirstViewModel 
     { 
      get { return _myFirstViewModel; } 
     } 

     private MyViewModel _mySecondViewModel; 
     public MyViewModel MySecondModel 
     { 
      get { return _mySecondViewModel; } 
     } 

     private DataModel _dataModel; 
     public DataModel DataModel 
     { 
      get { return _dataModel; } 
     } 

     public MainViewModel() 
     { 
      _dataModel = new DataModel(); 
      _myFirstViewModel = new MyViewModel(_dataModel.DataLists[0]); 
      _mySecondViewModel = new MyViewModel(_dataModel.DataLists[0]); 
     } 
    } 
} 

using System; 
using System.Collections.Generic; 

namespace BindingTest1 
{ 

    public class DataModel 
    { 
     private List<string>[] _dataLists; 
     public List<string>[] DataLists 
     { 
      get { return _dataLists; } 
     } 


     public DataModel() 
     { 

      List<string> list0 = new List<string> { "One", "Two", "Three" }; 
      List<string> list1 = new List<string> { "Alpha", "Beta", "Gamma" }; 
      _dataLists = new List<String>[] { list0, list1 }; 
     } 
    } 
} 

MainWindow.xaml DataModel.csに、私のデータモデルを持っている

<Window x:Class="BindingTest1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:BindingTest1" 
     mc:Ignorable="d" 
     xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase" 
     Title="MainWindow" Height="350" Width="525"> 

    <Window.DataContext> 
     <local:MainViewModel/> 
    </Window.DataContext> 

    <Grid> 

     <StackPanel HorizontalAlignment="Stretch" Height="100" VerticalAlignment="Top" Orientation="Horizontal"> 

     <!-- These were just to check the data was being set up properly -->  
     <ListBox x:Name="listBox1" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" ItemsSource="{Binding DataModel.DataLists[0]}"/> 
     <ListBox x:Name="listBox2" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" ItemsSource="{Binding DataModel.DataLists[1]}"/> 

     <!-- this is what I want to be able to do --> 
     <local:MyView ViewModel="{Binding MyFirstViewModel}"/> 
     <local:MyView ViewModel="{Binding MySecondViewModel}"/> 

     </StackPanel> 

    </Grid> 
</Window> 

(分離コードがデフォルトです)

MyViewModel .csファイル

using System; 
using System.Collections.Generic; 

namespace BindingTest1 
{ 
    public class MyViewModel 
    { 
     private List<string> _dataList; 
     public List<string> DataList 
     { 
      get { return _dataList; } 
     } 

     public MyViewModel(List<string> list) 
     { 
      _dataList = new List<String>(list); 
      _dataList.Add("Some Local Processing"); 
     } 
    } 
} 

MyView.xaml

<UserControl x:Class="BindingTest1.MyView" 
      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:local="clr-namespace:BindingTest1" 
      mc:Ignorable="d" 
      d:DesignHeight="100" d:DesignWidth="100"> 
    <Grid> 
     <ListBox x:Name="listBox" HorizontalAlignment="Left" Height="100" VerticalAlignment="Top" Width="100" ItemsSource="{Binding ViewModel.DataList}"/> 
    </Grid> 
</UserControl> 

分離コード

using System.Windows; 
using System.Windows.Controls; 

namespace BindingTest1 
{ 
    /// <summary> 
    /// Interaction logic for MyView.xaml 
    /// </summary> 
    public partial class MyView : UserControl 
    { 
     public MyViewModel ViewModel 
     { 
      get { return (MyViewModel)GetValue(ViewModelProperty); } 
      set { SetValue(ViewModelProperty, value); } 
     } 

     public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register("ViewModel", typeof(MyViewModel), typeof(MyView), 
      new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None, new PropertyChangedCallback(OnViewModelChanged))); 

     public MyView() 
     { 
      InitializeComponent(); 
     } 

     private static void OnViewModelChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
     { 
      // Just making sure the right thing is being received 
      List<string> dataList = (e.NewValue as MyViewModel).DataList; 
      foreach(string line in dataList) 
      { 
       System.Console.WriteLine(line); 
      } 
     } 
    } 
} 
+0

通常、ユーザーコントロールごとに特殊なビューモデルは必要ありません。 xamlにいくつかの定数値を代入すると、カスタムのユーザーコントロールが動作するはずです。bidningsはDataContextから値を取ることが期待されます。あなたがそのように行くなら、ここを見てください[似たような問題](https://stackoverflow.com/questions/46972319/wpf-usercontrol-doesnt-inherit-parent-datacontext) – ASh

答えて

0

私はあなたがここで依存関係プロパティを必要とは思いません。

これを試してください。

<local:MyView DataContext="{Binding MyFirstViewModel}"/> 
<local:MyView DataContext="{Binding MySecondViewModel}"/> 

DataListをMyView XAMLのItemsSourceにバインドします。

MyFirstViewModelをMyViewのDataContextに割り当てた場合、内部のバインディングはItemsSourceのMyFirstViewModelを検索します。

+0

感謝します!今私はそれを見ているようにはっきりしているようですが、私はサークルで回ってきました。 –

0

は、ここであなたがこれを行うべき方法です。ビューにViewModelプロパティは必要ありません。それは、ViewModelとなるDataContextのプロパティにバインドする必要があります。

ビュー:

ItemsSource="{Binding DataList}" 

ウィンドウ:

<Window.Resources> 
    <DataTemplate DataType="{x:Type local:MyViewModel}"> 
     <local:MyView 
      /> 
    </DataTemplate> 
</Window.Resources> 

<Grid> 

    <StackPanel HorizontalAlignment="Stretch" Height="100" VerticalAlignment="Top" Orientation="Horizontal"> 

     <!-- ... --> 

     <ContentControl Content="{Binding MyFirstViewModel}"/> 
     <ContentControl Content="{Binding MySecondViewModel}"/> 
    </StackPanel> 
+0

ありがとう、私はまだ使い慣れていますWPFには、DataContextは私がバインドできるもう一つのことだと私と一緒にクリックしていませんでした。 –

関連する問題