2016-04-27 18 views
0

私はWPFの初心者です。そしてこの例はうまくいきます。 https://msdn.microsoft.com/en-us/data/jj574514.aspxWPF - MVolVMを使用してICollectionViewをデータグリッドにバインドする方法

今、MVVMに従うように変更しようとしています。ここで

はここでメインウィンドウXAML

<Window 
    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:WPFwithEFSampleCodeFirst" mc:Ignorable="d" x:Class="WPFwithEFSampleCodeFirst.MainWindow" 
    Title="MainWindow" Height="352.134" Width="517.53" Loaded="Window_Loaded"> 

<Grid Margin="0,0,0,-3"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="0*"/> 
     <ColumnDefinition Width="77*"/> 
     <ColumnDefinition Width="25*"/> 
    </Grid.ColumnDefinitions> 
    <Button Content="Save" Grid.Column="2" HorizontalAlignment="Left" Margin="41,167,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/> 
    <DataGrid Grid.ColumnSpan="2" ItemsSource="{Binding Categories}" AutoGenerateColumns="False" HorizontalAlignment="Left" Margin="32,10,0,0" VerticalAlignment="Top" Height="124" Width="330" > 
     <DataGrid.Columns> 
      <DataGridTextColumn Width="SizeToHeader" Header="Category Id" Binding="{Binding Path = CategoryId}"/> 
      <DataGridTextColumn Width="SizeToHeader" Header="Name" Binding="{Binding Path = Name}"/> 
     </DataGrid.Columns> 
    </DataGrid> 

    <DataGrid Grid.ColumnSpan="2" AutoGenerateColumns="False" HorizontalAlignment="Left" Margin="32,153,0,0" VerticalAlignment="Top" Height="146" Width="330"> 
     <DataGrid.Columns> 
      <DataGridTextColumn Binding="{Binding CategoryId}" Header="Category Id" Width="SizeToHeader"/> 
      <DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="SizeToHeader"/> 
      <DataGridTextColumn Binding="{Binding ProductId}" Header="Product Id" Width="SizeToHeader"/> 
     </DataGrid.Columns> 
    </DataGrid> 
</Grid> 

である私はViewModelにに2つ目の詳細データグリッドをバインドする方法がわからないMainWindowViewModel

class MainWindowViewModel 
{ 
    private ICollectionView _categoryView; 

    public ICollectionView Categories 
    { 
     get { return _categoryView; } 
    } 

    ProductContext context = new ProductContext(); 

    public MainWindowViewModel() 
    { 
     IList<Category> categories = GetCategories(); 
     _categoryView = CollectionViewSource.GetDefaultView(categories); 

    } 

    public IList<Category> GetCategories() 
    { 
     return context.Categories.ToList(); 
    } 
} 

です。私は元の例と同じマスター - 詳細表示機能を持っていたいと思います。

カテゴリの商品を2番目のデータグリッドにバインドするにはどうすればいいですか? MVVMを使用して実装する正しい方法は何ですか?


さらに詳しい情報:

public class Category 
{ 
    public Category() 
    { 
     this.Products = new ObservableCollection<Product>(); 
    } 

    public int CategoryId { get; set; } 
    public string Name { get; set; } 

    public virtual ObservableCollection<Product> Products { get; private set; } 
} 

    public class Product 
{ 
    public int ProductId { get; set; } 
    public string Name { get; set; } 

    public int CategoryId { get; set; } 
    public virtual Category Category { get; set; } 
} 

    public class ProductContext : DbContext 
{ 
    public DbSet<Category> Categories { get; set; } 
    public DbSet<Product> Products { get; set; } 
} 

答えて

0

バインドマスターデータグリッドのSelectedItemプロパティへのSelectedItemプロパティには、詳細データグリッドのDataContextのをバインドすることですViewModelのプロパティ

<DataGrid SelectedItem="{Binding SelectedCategory}" Grid.ColumnSpan="2" ItemsSource="{Binding Categories}" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Width="SizeToHeader" Header="Category Id" Binding="{Binding Path = CategoryId}"/> 
     <DataGridTextColumn Width="SizeToHeader" Header="Name" Binding="{Binding Path = Name}"/> 
    </DataGrid.Columns> 
</DataGrid> 

MainWindowViewModel

private Category _selectedCategory; 

public Category SelectedCategory 
{ 
    get { return _selectedCategory; } 
    set 
    { 
     _selectedCategory = value; 
     OnPropertyChanged("SelectedCategory"); 
     OnPropertyChanged("SelectedCategoryProducts"); 
    } 
} 

(これはINotifyPropertyChangedのを実装するために、あなたのビューモデルが必要です。 OnPropertyChangedをこの方法は、PropertyChangedイベントハンドラが呼び出されます)

ビューモデルで

<DataGrid ItemsSource="{Binding SelectedCategoryProducts}" Grid.ColumnSpan="2" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Binding="{Binding CategoryId}" Header="Category Id" Width="SizeToHeader"/> 
     <DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="SizeToHeader"/> 
     <DataGridTextColumn Binding="{Binding ProductId}" Header="Product Id" Width="SizeToHeader"/> 
    </DataGrid.Columns> 
</DataGrid> 
+0

あなたのコードで2つのことが変更され、うまくいきました。 1. SelectedCategoryProductsのタイプは、カテゴリ2の代わりにObservableCollection でなければなりません。DataGridバインディングの詳細は、DataContext = "{SelectedCategoryProducts、ElementName = MasterGridのバインディング"ではなく "ItemsSource =" {Binding SelectedCategoryProducts} "に変更されます。 –

+0

元の例では、非常に簡単な2つのマスター詳細のデータグリッドをバインドするためのデータソースのドラッグアンドドロップ方式です。 MVVMに移行すると、簡単な方法ではなく、公共の財産に縛らなければなりません。 –

0

最も簡単な方法は、マスター・データグリッド

<DataGrid x:Name="MasterGrid" Grid.ColumnSpan="2" ItemsSource="{Binding Categories}" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Width="SizeToHeader" Header="Category Id" Binding="{Binding Path = CategoryId}"/> 
     <DataGridTextColumn Width="SizeToHeader" Header="Name" Binding="{Binding Path = Name}"/> 
    </DataGrid.Columns> 
</DataGrid> 

<DataGrid DataContext="{Binding SelectedItem.Products, ElementName=MasterGrid}" Grid.ColumnSpan="2" AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Binding="{Binding CategoryId}" Header="Category Id" Width="SizeToHeader"/> 
     <DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="SizeToHeader"/> 
     <DataGridTextColumn Binding="{Binding ProductId}" Header="Product Id" Width="SizeToHeader"/> 
    </DataGrid.Columns> 
</DataGrid> 
+0

こんにちは、上記のクラス定義に関する更新を確認できますか?私は2番目の詳細テーブルに製品をバインドしようとしています。 SelectedItemをバインドすることはできません。 –

+0

@AppleJuice 'SelectedItem.Products'へのバインディングパスを変更することはできますか? –

+0

いいえ、SelectedItem.Productsは機能しません。 2番目の詳細データグリッドには何も表示されません。 –

0

でSelectedCategoryProductsプロパティに選択したカテゴリの製品特性に

public ObservableCollection<Product> SelectedCategoryProducts 
{ 
    get 
    { 
     if (_selectedCategory == null) return null; 

     return _selectedCategory.Products; 
    } 
} 

バインド詳細データグリッドを返す別のプロパティを追加します。 ICollectionViewその機能を使用しないことは残念です...

まず、se最初のデータグリッド(カテゴリ)はIsSynchronizedToCurrentItem="true"です。

次に、2番目のDataGridで、ItemsSource="{Binding Categories.CurrentItem.Products}"というデータソースをバインドします。ここで、カテゴリはビューモデルICollectionViewです。

IsSynchToCurrentItem=trueの効果は、ICollectionViewがあなたのためにあなたの現在のアイテムを追跡するためにあなたのビューモデル内のプロパティを保持する必要はないということです。

次に、ユーザーがデータグリッド内の行を選択するたびに、ビューモデル内で現在のアイテムが設定されるたびに、現在のアイテムがビューモデル内で変更され(通知するにはICollectionViewのイベントがあります)対応する行が選択されます。

ICollectionViewを使用すると、ソースコレクションに触れることなくソート、フィルタリング、グループ化することができ、とりわけ現在のアイテムをプログラムで変更することができます。モデルを見て、などMoveCurrentTo(object target)MovecurrentToFirst()など....

あなたのビジネスのC#のモデルは結構ですので、あなたのXAMLが見える方法を使用して、XAMLのCONTROL(および対応する視覚/ XAMLのitemcontrolにおけるので、選択された行)そのように:

<DataGrid Grid.ColumnSpan="2" IsSynchronizedToCurrentItem="true" ItemsSource="{Binding Categories}" AutoGenerateColumns="False" HorizontalAlignment="Left" Margin="32,10,0,0" VerticalAlignment="Top" Height="124" Width="330" > 
    <DataGrid.Columns> 
     <DataGridTextColumn Width="SizeToHeader" Header="Category Id" Binding="{Binding Path = CategoryId}"/> 
     <DataGridTextColumn Width="SizeToHeader" Header="Name" Binding="{Binding Path = Name}"/> 
    </DataGrid.Columns> 
</DataGrid> 

<DataGrid Grid.ColumnSpan="2" ItemsSource="{Binding Categories.CurrentItem.Products}" AutoGenerateColumns="False" HorizontalAlignment="Left" Margin="32,153,0,0" VerticalAlignment="Top" Height="146" Width="330"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Binding="{Binding CategoryId}" Header="Category Id" Width="SizeToHeader"/> 
     <DataGridTextColumn Binding="{Binding Name}" Header="Name" Width="SizeToHeader"/> 
     <DataGridTextColumn Binding="{Binding ProductId}" Header="Product Id" Width="SizeToHeader"/> 
    </DataGrid.Columns> 
</DataGrid> 
関連する問題