2016-05-26 22 views
3

関連する子ビューを含むItemsControlにバインドするViewModelsのObservableCollectionがあります。 ViewModelをコレクションに追加すると、適切な数の子ビューがItemsControlに生成されます。ただし、生成された各ビューのDataContextはnullです。子ビューをインライン化すると正しく動作します。ですから、私の子ビューのDataContextをViewModelに設定するためには何が必要ですか?ItemsControlでDataTemplateとしてViewを使用するとDataContextが設定されない

はここに私の親のViewModel内のrelaventのビットです:

public ObservableCollection<ChildViewModel> Numbers { get; set; } 

    public ParentViewModel() 
    { 
     Numbers = new ObservableCollection<ChildViewModel>(); 
    } 

    private void ShowNumbers() 
    { 
     foreach (var num in Enumerable.Range(0, number)) 
     { 
      var childView = new ChildViewModel(number.ToString()); 
      Numbers.Add(childView); 
     } 
    } 
親ビューから

関連ビット:

 <ItemsControl ItemsSource="{Binding Numbers, UpdateSourceTrigger=PropertyChanged}"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate DataType="{x:Type vm:ChildViewModel}"> 
        <v:ChildView /> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 

子ビュー:

<UserControl x:Class="TestWpfApp.Views.ChildView" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:prism="http://prismlibrary.com/"    
     prism:ViewModelLocator.AutoWireViewModel="True"> 
<Grid> 
    <Label Content="{Binding NumberString}" Width="30" Height="30" BorderThickness="1" BorderBrush="Black" HorizontalAlignment="Center"/> 
</Grid> 
</UserControl> 

子供のViewModel:

public class ChildViewModel : BindableBase 
{ 
    private string numberString; 
    public string NumberString 
    { 
     get 
     { 
      return numberString; 
     } 
     set 
     { 
      SetProperty(ref numberString, value); 
     } 
    } 

    public ChildViewModel() { } 

    public ChildViewModel(string number) 
    { 
     NumberString = number; 
    } 
} 

明らかに、私は何かが誤って構成されていますが、私の人生にとって何が分かりませんか?

はFYI私はプリズムライブラリ

+2

プリズム:ViewModelLocator.AutoWireViewModel'を設定しないでください。WPFは既にItemControl内のアイテムコンテナのDataContextプロパティの設定に注意しているからです。参照:http://stackoverflow.com/q/33043978/1136211 – Clemens

+0

'DataContext'はあなたの' ViewModel'に設定されていますか?または単に 'DataTemplate's'は適用できませんか?いくつかの 'string'プロパティを作成し、あなたの' DataContext'がセットされているかどうかをテストする 'View'をバインドしてください。 – StepUp

+0

まあ@Clemens、あなたは絶対に正しかったです。そのコード行を削除すると、すべての作業が完了しました。それを回答として提出すれば、私はそれを容認された解決策にしたいと思います。 – greenjaed

答えて

2

それはItemTemplateに継承できるように、WPFは自動的に、適切な項目インスタンスへItemsControlの項目のコンテナ要素のDataContextを設定します。どうやら、このメカニズムはprism:ViewModelLocator.AutoWireViewModelプロパティを設定すると無効になります。

だから、ちょうどあなたのChildViewのXAMLからそれを削除します。そのため、一般的なルールとして

<UserControl x:Class="TestWpfApp.Views.ChildView" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:prism="http://prismlibrary.com/"> 
    <Grid> 
     <Label Content="{Binding NumberString}" Width="30" Height="30" 
       BorderThickness="1" BorderBrush="Black" HorizontalAlignment="Center" /> 
    </Grid> 
</UserControl> 

を、ユーザーコントロールは、明示的、どちらも直接もAutoWireViewModelのような機構により、DataContext、独自に設定してはいけません効果的に親コントロールからDataContextを継承しません。

1

子ビューの適切な数がItemsControlにして生成されるを使用しています。
viewModelにはDataContextが正しく設定されていますが、DataTemplate'sは適用されていないと判断できます。

私は同じ問題を抱えており、私はまたPrismライブラリを使用しています。私はどのようにそれを行うことができる方法について共有したいと思います。多分それはあなたに役立つでしょう。私はCompositeCollection使用しました:

のViewModel:

public class MainWindowVM:ViewModelBase 
{ 
    public MainWindowVM() 
    { 
     LoadData(); 
    } 
    private void LoadData() 
    {    
     ObservableCollection<Human> coll = new ObservableCollection<Human>(); 
     for (int indexLoop = 0; indexLoop < 5; indexLoop++) 
     { 
      if (indexLoop % 2 == 0) 
      { 
       coll.Add(new Sportsman() {FirstName=indexLoop.ToString(), LastName=indexLoop.ToString()}); 
      } 
      else 
      { 
       coll.Add(new Employee() { FirstName = indexLoop.ToString(), LastName = indexLoop.ToString()}); 
      }     
     } 
     CompositeCollection compositeColl = new CompositeCollection(); 
     compositeColl.Add(new CollectionContainer() { Collection = coll }); 
     FooData = compositeColl; 
    } 

    private CompositeCollection fooData; 

    public CompositeCollection FooData 
    { 
     get { return fooData; } 
     set 
     { 
      fooData = value; 
     } 
    } 

} 

モデル:

public class Human 
{   
    private string firstName; 
    public string FirstName 
    { 
     get { return firstName; } 
     set { firstName = value; } 
    } 

    private string lastName; 
    public string LastName 
    { 
     get { return lastName; } 
     set { lastName = value; } 
    } 
} 

public class Sportsman:Human 
{ } 

public class Employee:Human 
{ } 

ビュー:

<Window x:Class="ItemsControlWithDataTemplates.MainWindow" 
    <!--The code is omitted for the brevity--> 
    Title="MainWindow" Height="350" Width="525"> 
    <Window.DataContext> 
     <vm:MainWindowVM/> 
    </Window.DataContext> 
    <Grid> 
     <ItemsControl ItemsSource="{Binding FooData}"> 
      <ItemsControl.ItemsPanel> 
       <ItemsPanelTemplate> 
        <VirtualizingStackPanel/> 
       </ItemsPanelTemplate> 
      </ItemsControl.ItemsPanel> 
      <ItemsControl.Resources> 
       <DataTemplate DataType="{x:Type model:Employee}"> 
        <StackPanel Orientation="Horizontal"> 
         <TextBlock Text="{Binding FirstName}"/> 
         <TextBlock Text=" (Employee"/> 
         <TextBlock Text="{Binding LastName}"/> 
         <TextBlock Text=")"/> 
        </StackPanel> 
       </DataTemplate> 
       <DataTemplate DataType="{x:Type model:Sportsman}"> 
        <StackPanel Orientation="Horizontal"> 
         <TextBlock Text="{Binding FirstName}"/> 
         <TextBlock Text=" - Sportsman "/> 
         <TextBlock Text="{Binding LastName}"/> 
        </StackPanel> 
       </DataTemplate> 
       <DataTemplate DataType="{x:Type model:Human}"> 
        <StackPanel Orientation="Horizontal"> 
         <TextBlock Text="{Binding FirstName}"/> 
         <TextBlock Text=" - "/> 
         <TextBlock Text="{Binding LastName}"/> 
        </StackPanel> 
       </DataTemplate> 
      </ItemsControl.Resources> 
     </ItemsControl>  
    </Grid> 
</Window> 

は、実際に私は私のPrismアプリケーションで次のようにDataContextを設定します。

public MyUserControl(IMyViewModel viewModel) 
{ 
    InitializeComponent(); 
    DataContext = viewModel; 
} 
関連する問題