【问题标题】:How to bind ObservableCollection with datagrid WPF如何将 ObservableCollection 与 datagrid WPF 绑定
【发布时间】:2016-09-01 11:15:38
【问题描述】:

我已经检查了这些链接,但没有解决我的问题。

我有两个模型类(Order.csOrderItems.cs)和一个 View(Invoice.xaml)

Order 类中有 ObservableCollection(OrderItem),Invoice.xaml 中有一个数据网格。我需要将 ObservableCollection 绑定到数据网格。 问题是,当项目添加到 ObservableCollection 时,通过编写 xaml 代码进行绑定不会自动更新数据网格。

代码如下所示

订单类

public class Order
{
    public Order()
    {
        OrderItems =new ObservableCollection<OrderItem>();
    }

    public ObservableCollection<OrderItem> OrderItems { get; set; }

    public void GetOrderDetails(string customerId)
    {
        // method for getting set of OrderItmes objects and add to the 
        // ObservableCollection<OrderItem>
    }
}

OrderItem 类

public class OrderItem
{
    public OrderItem(string supplierId, string itemId, string    itemName,decimal weight)
    {
        // some codes here
    }
    public string SupplierId { get; set; } // Supplier's ID
    public string ItemId { get; set; } // Item ID
    public string ItemName { get; set; }// Item Name
    public decimal Weight { get; set; } // weight of the item
}

Invoice.xaml 的 xaml 代码(为简单起见,仅显示必要的代码。Model 是 Order 和 OrderItem 类的包。

    xmlns:model="clr-namespace:Onion.Model"
<Window.Resources>
    <model:Order x:Key="Order"/>
</Window.Resources>

<DataGrid x:Name="dataGrid" AutoGenerateColumns="False" CanUserResizeRows="False" Grid.ColumnSpan="8"
            Margin="0,0,30.5,0" CanUserResizeColumns="False" CanUserReorderColumns="False"
            CanUserSortColumns="False" CanUserAddRows="False" IsReadOnly="True"
            DataContext="{Binding Source={StaticResource Order}}" ItemsSource="{Binding OrderItems}">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding SupplierId}" CanUserResize="False" FontSize="16"
                    Header="Supplier" Width="0.18*" />
                <DataGridTextColumn Binding="{Binding ItemId}" CanUserResize="False" FontSize="16"
                    Header="ItemID" Width="0.13*" />
                <DataGridTextColumn Binding="{Binding ItemName}" CanUserResize="False" FontSize="16"
                    Header="Item name" Width="0.2*" />
                <DataGridTextColumn Binding="{Binding Weight}" CanUserResize="False" FontSize="16" 
                    Header="Weight" Width="0.1*" />

 </DataGrid>

但我可以通过在必要的 Invoice.xaml.cs 类中编写代码来实现此目的,而无需编写 xaml 代码。

    private void txtBox_PreviewKeyDown(object sender, KeyEventArgs e){
    Order _order = new Order();
    _order.GetOrderDetails(customerId);// add OrderItems to the ObservableCollection

    // If this code is written some xaml codes are not needed (they are shown  below in the question
    dataGrid.ItemsSource = _order.OrderItems; // OrderItems is the ObservableCollection<OrderItem>  
}

(包括将每一列绑定到 OrderItem 中的一个属性)如果行 dataGrid.ItemsSource = _order.OrderItems; 则不需要以下代码被使用了。

xmlns:model="clr-namespace:Onion.Model"
<Window.Resources>
    <model:Order x:Key="Order"/>
 </Window.Resources>
 DataContext="{Binding Source={StaticResource Order}}" ItemsSource="{Binding OrderItems}"

谁能告诉我如何克服这个问题。

【问题讨论】:

  • 您绑定到的Order 与您在事件处理程序中修改的不是同一个。
  • 您如何将 OrderItem 添加到您的订单中?
  • @Nitin 通过 GetOrderDetails(string customerId) 方法将 OrderItems 添加到 ObservableCollection OrderItems
  • @CharlesMager 在事件处理程序中修改是什么意思?在那里,我已将 ObservableCollection 分配给数据网格的项目源。没有这个界限,它是完美的工作我需要的是没有代码 datagrid.ItemSource = _order.OrderItems;

标签: c# wpf xaml data-binding datagrid


【解决方案1】:

您的网格绑定到Order 静态资源:

<Window.Resources>
    <model:Order x:Key="Order"/>
</Window.Resources>

<DataGrid DataContext="{Binding Source={StaticResource Order}}" ...

在您的事件处理程序中,您正在创建一个新的 Order 实例:

Order _order = new Order();

然后您调用一个方法,您说,该方法将OrderItem 添加到_order 中的OrderItems 集合中。这不是您的DataGrid.ItemsSource 绑定到的OrderItems 集合。

一个简单的解决方法可能是在后面的代码中声明您的Order,并将其分配给构造函数中的DataContext

private readonly Order _order = new Order();

public WindowName()
{
    DataContext = _order;
}

然后从DataGrid 中删除DataContext 绑定(它将继承Window.DataContext)。然后,您可以从事件处理程序中删除 Order _order = new Order() 并改用实例字段 _order

理想情况下,不需要您的事件处理程序,并且您的Order 中会有一个ICommand,它将绑定到应该添加新订单的任何按钮。

【讨论】:

    【解决方案2】:

    当您填充数据时,您需要告诉框架数据已更新。

    因此,从集合的 Setter 中的 Viewmodel 代码中,添加一行内容 RaisePropertyChanged("OrderItems") 这是您告诉网格的绑定源名称。

    这个工作流程是:

    1. 在您的 Xaml 中添加 ItemsSource="{Binding Orders}"。这将是 propertychanged 的​​名称,用于向框架发出信号已更改。
    2. 在您的视图模型代码中,当您对集合进行更改时,您将发出 RaisePropertyChanged("Orders") 信号,通知框架将数据编组到 UI 组件。
    3. 下一步将确定数据是从代码流向 UI,还是从 UI 流向代码,或者双向。因此,在您的 xaml ItemSource="{Binding Orders, Mode=OneWay} 中。当您在 Visual Studio 中时,它会弹出整个列表。在双向模式下,框架会将您的数据从 UI 编组到 observablecollection。

    抱歉,我没有时间修改您的代码。希望这能很好地解释它。 干杯。

    【讨论】:

      猜你喜欢
      • 2015-01-26
      • 2014-08-23
      • 1970-01-01
      • 2013-10-14
      • 2015-04-02
      • 1970-01-01
      • 1970-01-01
      • 2017-02-08
      • 2016-08-28
      相关资源
      最近更新 更多