WPF датагрид с MVVM - PullRequest
       1

WPF датагрид с MVVM

8 голосов
/ 10 августа 2011

Я пытаюсь привязать сетку данных в WPF к моей ViewModel, чтобы она обновляла любые изменения ячеек в базе данных, а также позволяла пользователю удалять строки и добавлять новые строки.У меня есть часть его работы, но я не могу найти ELEGANT решение для ADD и изменить.здесь xaml

<DataGrid AutoGenerateColumns="false" HorizontalAlignment="Left" Margin="26,41,0,0" Name="dataGrid1"   
              ItemsSource="{Binding Path=GetAllItems}" Height="200" VerticalAlignment="Top" Width="266" >
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding Path=ItemListID}" Header="ID" Visibility="Hidden"/>
            <DataGridTextColumn Binding="{Binding Path=ItemName}" Header="Name" Width="4*" />
            <DataGridCheckBoxColumn Binding="{Binding Path=IsActive}" Header="Active" Width="*"  />
        </DataGrid.Columns>

, тогда в моем представлении метод модели

private ObservableCollection< ItemsList> getAllItems()
{
    using (var context = new InspectorGeneralEntities())
    {
        var query = from I in context.ItemsLists
                    select I;

        var item = new ObservableCollection<ItemsList>(query.ToList());
        return item;
    }
}

Удаление строки или изменение строки в сетке данных не поступает в базу данных.

a) Какие еще привязки мне нужно создать в коде xaml, который будет обнаруживать эти события

b) Как мне обнаружить удаленную запись или измененный элемент в модели представления, чтобыЯ могу обновить текст данных, если он не будет автоматически.

Ответы [ 4 ]

1 голос
/ 13 февраля 2013

Я вижу пару проблем с кодом в вашем вопросе.Но причина, по которой удаление строки не отражается в базе данных, заключается в .ToList () - по сути, вы создаете новый список, который является копией запроса и сеткиудаляет элементы из этой копии.

Вы должны использовать ListCollectionView и использовать Filter вместо оператора linq.

Вот пример, показывающийкак это сделать:

1) Создать новый проект WPF с именем ListCollectionViewTest

2) В MainWindow.xaml.cs вырезать и вставить следующее (должно быть в ViewModel, ноМне лень)

    using System.Collections.Generic;
    using System.Linq;
    using System.Windows;
    using System.Windows.Data;

    namespace ListCollectionViewTest
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            private List<Employee> equivalentOfDatabase = new List<Employee>()
                        {
                            new Employee() { FirstName = "John", LastName = "Doe", IsWorthyOfAttention = true },
                            new Employee() { FirstName = "Jane", LastName = "Doe", IsWorthyOfAttention = true },
                            new Employee() { FirstName = "Mr.", LastName = "Unsignificant", IsWorthyOfAttention = false },
                        };

            public ListCollectionView TestList { get; set; }
            public MainWindow()
            {
                DataContext = this;

                // This is all the magic you need -------
                TestList = new ListCollectionView(equivalentOfDatabase);
                TestList.Filter = x => (x as Employee).IsWorthyOfAttention;

                InitializeComponent();
            }

            private void Button_Click(object sender, RoutedEventArgs e)
            {
                MessageBox.Show(equivalentOfDatabase.Aggregate("Employees are: \n\r", (acc, emp) => acc + string.Format("    - {0} {1}\n\r", emp.FirstName, emp.LastName), x => x));
            }
        }

        public class Employee
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public bool IsWorthyOfAttention { get; set; }
        }
    }

3) В MainWindow.xaml вырезать и вставить это:

    <Window x:Class="ListCollectionViewTest.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525">

        <StackPanel>
            <DataGrid ItemsSource="{Binding TestList}"
                      RowHeight="22"
                      AutoGenerateColumns="True">
            </DataGrid>
            <Button Content="Show All Employees in DB" Click="Button_Click" />
        </StackPanel>        
    </Window>
1 голос
/ 10 августа 2011

Просто подпишитесь на событие CollectionChanged вашей ObservableCollection. Обработчик событий получает экземпляр класса NotifyCollectionChangedEventArgs , который содержит свойство Action, описывающее, были ли строки добавлены или удалены. Он также содержит списки строк, которые были добавлены («NewItems») или удалены («OldItems»). Это должно дать вам достаточно информации для обновления вашей базы данных.

Вы можете внедрить INotifyPropertyChanged в своей строке ViewModel (класс ItemsList я думаю), а затем подписаться на нее, чтобы выяснить, не является ли строка грязной и требует ли ее обновления в базе данных. Интерфейс состоит из одного события PropertyChanged, которое вызывается в установщиках свойств вашей ViewModel при каждом изменении значения.

Вы правы, событие NotifyCollectionChanged наступает слишком рано для немедленной вставки в базу данных. Но вы можете пометить строку как «вставленную» в обработчике событий и вставить ее, как только произойдет событие последнего изменения свойства (см. Выше), необходимое для завершения строки.

0 голосов
/ 19 апреля 2013

Вы можете создать новый ViewModel CLass: ItemGridVM для представления каждого объекта строки, т.е. ItemGridVM предоставляет свойства класса Item, которые вы связываете в своей сетке данных.Например:

public class ItemGridVM : BaseViewModel
    {
    private Item _item;//an instance of Item class
      public int ItemId
              {
                  get
                  {
                      return _item.ItemId;
                  }
                  set
                  {
                      _item.ItemId = value;
                      //if you want UI changes : raise PropertyChanged Notification and binding in UI should be Update SourceTrigger:PropertyChanged
                  }
        }
   //Contains Commands :UpdateItem,EditItem,DeleteItem
}

Теперь в yourMainViewModel вы можете создать наблюдаемую коллекцию ItemGridVM как:

private ObservableCollection<ItemGridVM> _getAllItems;

public ObservableCollection<ItemGridVM> GetAllItems
{
get
            {
                return _getAllItems;
            }
            set
            {
                _getAllItems = value;
                //if u want Observable Collection to get updated on edit either 
                RaisePropertyChanged("GetAllItems");

            }
}

Теперь в случае любого действия в любой строке команда связывается с ItemGridVM.получить детали строки в виде открытых свойств.Я решил ту же проблему, используя это. (Pure MVVM)

0 голосов
/ 26 февраля 2013

Ваш контекст данных не существует во время создания обновлений.Вы используете оператор «using», который разрушает контекст.Единственная причина, по которой вы видите данные, заключается в том, что вы принудительно выполняете запрос к вашей БД (с помощью оператора .ToList ()).Чтобы ответить на ваши вопросы:

a) больше ничего не нужно специально для привязки b) вызов SaveChanges () в вашем контексте InspectorGeneralEntities () обновит все изменения в вашей базе данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...