【问题标题】:How auto update db from datagrid如何从数据网格自动更新数据库
【发布时间】:2018-04-03 16:51:22
【问题描述】:

我正在使用 VB/wpf 和 SQL Server。我没有使用 mvvm、数据表、按钮、数据集或 Windows 窗体。在这种情况下和几天的搜索,我找不到从网格中保存数据的最后一步。

我的数据库表跟踪捐赠;它具有通常的预期字段。这是我目前所拥有的:

XAML (sn-p):

<Window.Resources>
    <CollectionViewSource
        Filter="Filter_By_Member"
        x:Key="cvsDonations">
    </CollectionViewSource>
.....
<DataGrid
    AutoGenerateColumns="False"
    CanUserReorderColumns="True"
    CanUserResizeColumns="True"
    CanUserResizeRows="False"
    CanUserDeleteRows="True"
    FontSize="13"
    FontWeight="Normal"
    ItemsSource="{Binding Source={StaticResource cvsDonations}}"
    Name="dgDonations"
    RowHeaderWidth="20"
    SelectionUnit="CellOrRowHeader"
    SelectionMode="Single">
    <DataGrid.Columns>
        <DataGridTextColumn
            Binding="{Binding Path=DateDue, Converter={StaticResource conDate}, StringFormat='MMM d, yyyy'}"
            ElementStyle="{StaticResource styDateBlock}"
            Header="Date Due"
            IsReadOnly="True"
            Width="90">
        </DataGridTextColumn>
.....

我的窗口包含一个 ComboBox 和网格。网格中的行取决于在 ComboBox 中选择的内容。这是执行此操作的代码。

Private Sub Change_Member(sender As Object, e As SelectionChangedEventArgs) Handles cboMembers.SelectionChanged
    cvsDonations.View.Refresh()
End Sub
Private Sub Filter_By_Member(sender As Object, e As FilterEventArgs)
    Dim PersonID As Long = CLng(cboMembers.SelectedValue)
    Dim d As Donation = DirectCast(e.Item, Donation)
    If d.PersonID = PersonID Then
        e.Accepted = True
    Else
        e.Accepted = False
    End If
End Sub

到目前为止一切正常。我还没有弄清楚如何自动更新底层数据库(使用已经编写和工作的存储过程)。更具体地说,我无法弄清楚要监视什么事件以及如何在代码中实现该事件。

基础集合是 ObservableCollection(Of Donation),并且 Donation 类已实现 INotifyPropertyChanged。我考虑过观察属性的变化,但是每次填充网格时都会触发该事件,因此这似乎不是正确的方法,此外我无法弄清楚如何实际引发适当的事件,即使这是这种方式去。

我尝试过使用 RowEditChanging 事件,这似乎是我想要的,但它在提交任何编辑之前被触发,因此该行包含的捐赠在触发此事件时具有旧值。

考虑到我的整体设置,什么是正确的方法以及应该如何实施?

【问题讨论】:

  • 它是 WPF,您无需绑定到事件来直接更新数据库 - 而是编写一个从视图模型中获取数据并使用该数据调用存储过程的服务。
  • @slugster 如前所述,我没有使用 mvvm,所以你的建议没有帮助。
  • 在使用 WPF 时为什么不使用 MVVM?您的cvsDonations 是您的数据对象列表,对吗?如果是这样,只需编写一个事件处理程序来侦听这些数据对象中的属性更改(在加载该列表时,您需要将该事件处理程序连接到每个对象),然后从事件处理程序建立一个数据库连接并调用存储过程并从调用事件处理程序的数据对象中传递信息。这是一种丑陋的做法。
  • @slugster 有很多关于 mvvm 在哪里以及不合适的文章。 SO上甚至还有一个。就我而言,事实并非如此。我的 OP 问题仍然存在。,

标签: wpf vb.net datagrid


【解决方案1】:

我建议这样做 -

你的 Donation 类应该有一个标志字段,比如说 Is_Dirty,它跟踪对象是否有修改。 最初在集合中加载项目时,请确保 Is_Dirty 设置为 false。当用户在网格上进行编辑并触发属性通知时,设置脏标志(来自属性设置器)。

为了保存,我建议有一个单独的按钮,单击它可以浏览集合中的所有脏对象并将更新传递给数据库。

通过绑定脏标志,您还可以更改修改行的外观,以便用户识别修改的行。

您还可以维护一个 State 属性,以了解对象是已添加、更新还是已删除。

通常,我将所有这些功能放在一个基类中,我的所有模型类(例如捐赠)都从该基类派生。

一些sn-p让你继续......

public abstract class ObservableDomainObject : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;
        private bool _isDirty;
        public ObservableDomainObject()
        {
            _state = ObjectState.Added;
            _isDirty = true;
        }

        private ObjectState _state;

        /// <summary>
        /// Get or Set 
        /// </summary>
        public ObjectState State
        {
            get { return _state; }
            set
            {
                if (_state != value)
                {
                    _state = value;
                    RaisePropertyChanged();
                }
            }
        }
        public void SetDirty(Boolean isDirty)
        {
            this.IsDirty = isDirty;
        }
        /// <summary>
        /// Check if the object is modified.
        /// </summary>
        public bool IsDirty
        {
            get { return _isDirty; }
            set
            {
                if (_isDirty != value)
                {
                    if (_state != ObjectState.Added && _state != ObjectState.Deleted)
                    {
                        this.State = value ? ObjectState.Modified : ObjectState.Unchanged;
                    }

                    _isDirty = value;
                    RaisePropertyChanged();
                }
            }
        }
        protected virtual void RaisePropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propertyName = "")
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }

            // Change Dirty flag when property changed.
            if (propertyName != "IsDirty")
                SetDirty(true);
        }
    }

    public enum ObjectState
    {
        /// <summary>
        /// New Record
        /// </summary>
        Added = 0,

        /// <summary>
        /// Unchanged after the load
        /// </summary>
        Unchanged,

        /// <summary>
        /// Modified 
        /// </summary>
        Modified,

        /// <summary>
        /// Deleted
        /// </summary>
        Deleted
    }

【讨论】:

  • 正如我的 OP 中所述,我希望更新自动发生。我不希望用户必须单击按钮来保存数据。此外,不需要维护状态数据,因为网格会告诉您更改是对现有数据的编辑还是新数据。
猜你喜欢
  • 1970-01-01
  • 2011-12-21
  • 2011-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-31
  • 2021-04-29
相关资源
最近更新 更多