Как добавить или удалить элемент через icollectionview и отразить в базе данных EF с помощью шаблона MVVM

Я новичок в WPF, и в настоящее время я создаю приложение с основными подробностями, используя Entity framework 6 (сначала код) на основе MVVM.

Вот пользовательский интерфейс.

введите описание изображения здесь

Master datagrid --- Категория

Подробности datagrid --- Продукт

Функции, которые мне нужны:

  1. Изменить, добавить, удалить элемент «Категория» или «Продукт»

  2. Через кнопку «сохранить» сохранить в базе данных.

  3. Фильтр категорий для управления отображаемыми элементами в основной сетке данных.

Я привязываю master datagrid к icollectionview «Категории» в моей модели представления.

<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="585.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"  Command="{Binding SaveCmd}" Grid.Column="1" HorizontalAlignment="Left" Margin="425,137,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click" Grid.ColumnSpan="2"/>
    <DataGrid x:Name="MasterGrid" SelectedItem="{Binding SelectedCategory}" ItemsSource="{Binding Categories}" Grid.ColumnSpan="2"   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="Category Name" Binding="{Binding Path = Name}"/>
        </DataGrid.Columns>
    </DataGrid>

    <DataGrid ItemsSource="{Binding SelectedCategoryProducts}" 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="Product Name" Width="SizeToHeader"/>
            <DataGridTextColumn  Binding="{Binding ProductId}" Header="Product Id" Width="SizeToHeader"/>
        </DataGrid.Columns>
    </DataGrid>
    <ComboBox ItemsSource ="{Binding DistinctCategoryName }" SelectedItem="{Binding SelectedCategoryName , Mode = TwoWay }"  IsSynchronizedWithCurrentItem="True" Grid.Column="1" HorizontalAlignment="Left" Margin="398,37,0,0" VerticalAlignment="Top" Width="120" Grid.ColumnSpan="2"/>
    <Label Content="Category Name filter" Grid.Column="1" HorizontalAlignment="Left" Margin="398,6,0,0" VerticalAlignment="Top" Grid.ColumnSpan="2"/>
</Grid>

ViewModel:

    class MainWindowViewModel:INotifyPropertyChanged
{
    ProductContext context = new ProductContext();

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

        DistinctCategoryName = GetDistinctCategoryName();
        _saveCmd = new RelayCommand(Save, CanSave);

    }

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

    private ICollectionView _categoryView;
    public ICollectionView Categories
    {
        get { return _categoryView; }
    }

    private string _selectedCategoryName;
    public string SelectedCategoryName
    {
        get { return _selectedCategoryName; }
        set
        {
            _selectedCategoryName = value;

            _categoryView.Filter = new Predicate<object>(GetFilteredView);
            _categoryView.Refresh();

            OnPropertyChanged("SelectedCategoryName");
        }
    }



    private IList<string> _distinctCategoryName;

    public IList<string> DistinctCategoryName
    {
        get { return _distinctCategoryName; }
        set 
        { 
            _distinctCategoryName = value;
            OnPropertyChanged("DistinctCategoryName");
        }

    }

    private List<string> GetDistinctCategoryName()
    {
        List<string> distCateName;
        List<Category> catelist = context.Categories.ToList();
        distCateName = catelist.Select(e => e.Name).Distinct().ToList();

        return distCateName;
    }


    private ICommand _saveCmd;
    public ICommand SaveCmd { get { return _saveCmd; } }
    public void Save(object obj)
    {   
        foreach (var product in context.Products.Local.ToList())
        {
            if (product.Category == null)
            {
                context.Products.Remove(product);
            }
        }


        context.SaveChanges();// What can I do Here to save the category change???

        //DistinctCategoryName = GetDistinctCategoryName();
    }

    public bool CanSave(object obj)
    {

        return true;
    }

    public bool GetFilteredView(object sourceObject)
    {
        Category cate = sourceObject as Category;
        if (cate.Name == _selectedCategoryName)
        {
            return true;
        }
        return false;
    }

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

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

            return _selectedCategory.Products;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void OnPropertyChanged(string propertyName)
    {
        //Fire the PropertyChanged event in case somebody subscribed to it
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

Проблемы:

Я привязываю ICollectionView к Master Datagrid из-за функции фильтрации. Действие категории добавить (добавить новую строку) или удалить (нажать клавишу «Удалить») нельзя сохранить в базе данных. (Я думаю, это потому, что я работаю над VIEW, а не с фактическим источником.) Итак, как правильно добавить / удалить элемент через icollectionview и отразить его в базе данных (источнике)? Или мне не стоит использовать ICollectionView?


person Apple Juice    schedule 29.04.2016    source источник


Ответы (1)


Наследуйте свой класс viewmodel от класса BindableBase.

Создайте свойство и частный член для категорий.

private ObservableCollection<DataClass> categories = new ObservableCollection<DataClass>();

public ObservableCollection<DataClass> Categories
{
get { return categories; }
set { SetProperty(ref categories, value); }
}

Теперь привяжите источник к Категории. Каждый раз, когда вы добавляете новый элемент, категории обновляются. По команде сохранения вы можете сохранить весь список или текущий выбранный элемент в базу данных. Дело в том, что вы можете получить событие изменения свойства класса или свойства в любой другой модели представления / представления и использовать это событие для сохранения ваших данных в базе данных.

person ViVi    schedule 29.04.2016
comment
Вы имеете в виду, что я должен привязать master datagird к категориям ObservableCollection ‹DataClass› вместо категорий ICollectionView? - person Apple Juice; 29.04.2016
comment
Как я могу выполнить функцию фильтрации по категориям ObservableCollection? - person Apple Juice; 29.04.2016
comment
Для этого вы можете использовать LINQ. Например: list.Where (m = ›m.SomeDataItem == FilterCondition select m) .ToList (); Это отфильтрует и предоставит вам список в соответствии с условием. - person ViVi; 30.04.2016
comment
Привет, не могли бы вы показать мне какой-нибудь код, как сохранить категории ObservableCollection ‹DataClass› обратно в базу данных Entity Framework? [В публичном сохранении void (объект obj)] - person Apple Juice; 02.05.2016
comment
Для этого вы можете повторно использовать уже существующий код. Надеюсь, вы знаете, как заполнить данные в таблице в базе данных с помощью entity framework, - person ViVi; 02.05.2016