0

私はWPFが初めてで、このリンクに従ってコードファーストメソッドを使用して例をビルドします。そして、例は機能します。 https://msdn.microsoft.com/en-us/data/jj574514.aspx

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

ここに MainWindow 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>

ここに 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 番目の詳細データグリッドを ViewModel にバインドする方法がわかりません。元の例と同じマスター詳細表示機能が欲しいです。

では、カテゴリ内の製品を 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; }
} 
4

3 に答える 3

0

ICollectionViewその機能を使わないのはもったいない…

まず、IsSynchronizedToCurrentItem="true"最初のデータグリッド (カテゴリ) を設定します。

次に、2 番目の DataGrid で、DataSource をItemsSource="{Binding Categories.CurrentItem.Products}"Where Categories is your view modelにバインドしますICollectionView

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

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

この機能に加えて、ICollectionView を使用すると、ソース コレクションに触れることなく、並べ替え、フィルター処理、およびグループ化を行うことができます。また、何よりも、XAML コントロールをいじることなく、ビュー モデル内の現在の項目をプログラムで変更できます(したがって、MoveCurrentTo(object target)MovecurrentToFirst()、などのメソッドを使用して、対応するビジュアル/XAML アイテム コントロールで選択された行)。

ビジネス C# モデルは問題ないので、XAML は次のようになります。

<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>
于 2016-08-03T15:25:42.273 に答える
0

最も簡単な方法は、詳細 DataGrid の DataContext をマスター DataGrid の SelectedItem プロパティにバインドすることです。

<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>
于 2016-04-27T20:35:56.680 に答える
0

マスター DataGrid の SelectedItem プロパティを 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 イベント ハンドラーを呼び出します)。

選択したカテゴリの製品プロパティを返す別のプロパティを追加します

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

        return _selectedCategory.Products;
    }
}

詳細 DataGrid をビュー モデルの SelectedCategoryProducts プロパティにバインドします。

<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>
于 2016-04-27T23:49:39.570 に答える