【问题标题】:How do I get the last row of a bound WPF Datagrid to notify View Model when the SelectedItem Changes?当 SelectedItem 更改时,如何获取绑定 WPF Datagrid 的最后一行以通知 View Model?
【发布时间】:2013-03-07 17:30:55
【问题描述】:

这是我的第一篇文章 - 如果需要,我欢迎任何关于如何发布问题的建议。

我有一个 WPF DataGrid,它的 ItemsSource 绑定到一个名为 OrderDetails(List Of OrderDetails) 的属性,SelectedItem 绑定到一个名为 CurrentOrderDetail 的属性。

在 CurrentOrderDetail 属性中,我调用了一个进行计算的方法。执行计算的方法循环通过 OrderDetails 属性并将属于该列表的每个 OrderDetail 的两个成员相乘以产生总成本。该方法只是简单地更新文本框绑定到表单上的另一个属性。

这一切都很好 - 直到我到达DataGrid 的最后一行。基本上,用户从第一行开始,单击 Invoiced 字段并输入数量并按 Enter 键,选择下一行。 SelectedItem 更改并因此更新 CurrentOrderDetail - 调用计算。这行得通!用户重复该过程,一切计算正常,直到DataGrid 中的最后一条记录被命中。当用户按 Enter 键结束对 Invoiced 单元格的编辑时,永远不会调用计算方法 - 因为 SelectedItem 没有更改,因此 CurrentOrderDetail 属性永远不会更新。

我喜欢标准,因为我最近转向 WPF/Silverlight 和 MVVM,所以我没有回头。因此,我试图以同样的方式保持这个应用程序。

我想我需要强制一些东西来触发SelectedItem 的变化。我曾考虑过在视图中连接事件并简单地强制导航,但这对我来说似乎有点难看。一定有更好的解决方案。我已经在这里和其他论坛度过了两天,并尝试了我自己的几个想法,但都没有奏效。

我可以要求用户导航到另一行以触发属性通知,但我宁愿不这样做。

这只是 DataGrid 的 XAML:

<DataGrid Name="grdData" Grid.Row="3" Grid.ColumnSpan="2" AutoGenerateColumns="False" CanUserAddRows="False" Margin="5,5,5,5" ItemsSource="{Binding Path=OrderDetails, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"  SelectedItem="{Binding Path=CurrentOrderDetail, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" BorderThickness="3" >
    <DataGrid.Columns>   
        <DataGridTextColumn Binding="{Binding Path=Part}" Header="Wyandot Part #" IsReadOnly="True" />
        <DataGridTextColumn Binding="{Binding Path=SupplierPartNumber}" Header="Supplier Part #" IsReadOnly="True" />
        <DataGridTextColumn Binding="{Binding Path=UnitPrice, StringFormat=c}" Header="Price" IsReadOnly="True" />
        <DataGridTextColumn Binding="{Binding Path=Account}" Header="Account" IsReadOnly="True" />
        <DataGridTextColumn Binding="{Binding Path=UDF5, Mode=TwoWay}" Header="Invoiced" IsReadOnly="False" />
    </DataGrid.Columns>
</DataGrid>

我的视图模型中的 sn-ps 是相关的。

Private m_orderDetails As List(Of OrderDetail)
Public Property OrderDetails As List(Of OrderDetail)
    Get
        Return m_orderDetails
    End Get
    Set(value As List(Of OrderDetail))
        m_orderDetails = value
        InvokePropertyChanged("OrderDetails")
    End Set
End Property

Private m_currentOrderDetail As OrderDetail
Public Property CurrentOrderDetail As OrderDetail
    Get
        Return m_currentOrderDetail
    End Get
    Set(value As OrderDetail)
        m_currentOrderDetail = value
        InvokePropertyChanged("CurrentOrderDetail")
        Calculate()
    End Set
End Property

Public Sub Calculate()
    Dim total As Decimal = 0

    For Each detail As OrderDetail In OrderDetails
        total += detail.UnitPrice * detail.UDF5
    Next

    PoTotal = CStr("$" & total.ToString)
End Sub

【问题讨论】:

标签: wpf mvvm datagrid selecteditem


【解决方案1】:

听起来你的计算发生在错误的更改事件上。我会让用户正在更新的OrderDetail 值属性触发属性更改事件并使用它来更新我的总数。

订阅每个OrderDetail 的每个属性更改事件需要做更多的工作,但这是您真正关心的。我可能会使用ObservableCollection&lt;OrderDetail&gt;,然后在Collectionchanged 事件中连接必要的侦听器。

【讨论】:

  • 回应两者,我已经想到了,但是我从 Entity 得到的(留下那部分 - 抱歉 - 使用 LINQ to Entity)是一个包含 ICollection 的 OrderHeader 对象(Master) (订单详情)(详情)。我想我可以迭代 ICollection 并将它们添加到可观察的集合中。我只需要在保存之前将这些更改推回 OrderHeader 的 IColleciton
  • 我感受到你的痛苦。由于这个或类似的原因,我发现自己一直在包装非常好的 EF 对象。但归根结底,多一层分离几乎总能让我的生活更轻松。
  • 确实!谢谢您的帮助!我很感激!
猜你喜欢
  • 1970-01-01
  • 2014-01-09
  • 2012-06-12
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 2011-08-31
  • 2015-08-04
  • 2021-12-08
相关资源
最近更新 更多