簡體   English   中英

WPF 數據網格與 MVVM

[英]WPF datagrid with MVVM

我正在嘗試將 WPF 中的數據網格綁定到我的 ViewModel,以便它將更新對數據庫的任何單元格更改,並允許用戶刪除行並添加新行。 我已經完成了部分工作,但找不到 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>

然后在我看來 model 方法

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) 我如何在 model 視圖中檢測到已刪除的記錄或修改的項目,以便如果它不會自動更新數據上下文。

我看到您問題中的代碼存在一些問題。 但是刪除行沒有反映在數據庫中的原因是.ToList() - 本質上,您正在創建一個新列表,它是查詢的副本,並且網格正在從該副本中刪除元素。

您應該使用ListCollectionView並使用Filter而不是 linq 語句。

這是一個示例,展示了如何執行此操作:

1) 創建一個名為ListCollectionViewTest的新 WPF 項目

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>

只需訂閱 ObservableCollection 的 CollectionChanged 事件。 事件處理程序接收NotifyCollectionChangedEventArgs class 的實例,其中包含描述是否已添加或刪除行的屬性“操作”。 它還包含已添加('NewItems')或刪除('OldItems')的行列表。 這應該為您提供足夠的信息來更新您的數據庫。

您可以在行 ViewModel 中實現INotifyPropertyChanged (我猜是ItemsList類),然后訂閱它,以查明行是否臟並需要在數據庫中更新。 該接口由單個事件PropertyChanged組成,每當值更改時,它將在 ViewModel 的屬性設置器中引發。

沒錯,NotifyCollectionChanged 事件來得太早,無法立即插入數據庫。 但是您可以在事件處理程序中將該行標記為“已插入”,並在完成該行所需的最后一個屬性更改事件(見上文)發生時立即插入它。

在您進行更新時,您的數據上下文不存在。 您正在使用破壞上下文的“使用”語句。 您看到數據的唯一原因是您已強制對您的數據庫運行查詢(通過 .ToList() 語句)。 要回答您的問題:

a) 不需要專門用於綁定 b) 在 InspectorGeneralEntities() 上下文中調用 SaveChanges() 將更新數據庫中的任何更改。

您可以創建一個新的 ViewModel CLass:ItemGridVM 來表示每一行 object 即 ItemGridVM 公開您在數據網格中綁定的項目 class 屬性。 例如:

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 的 Observable COllection,如下所示:

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。因此,您可以將行詳細信息作為公開的屬性。 我用這個解決了同樣的問題。(純MVVM)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM