Reputation: 601
I've already checked these links but didn't solve my problem.
I have two model classes(Order.cs and OrderItems.cs) and a View(Invoice.xaml)
There is ObservableCollection(OrderItem) in Order class and a datagrid in the Invoice.xaml. I need to bind ObservableCollection to the datagrid. Problem is, binding by writing xaml codes does not automatically update the datagrid when items are added to the ObservableCollection.
Codes are shown below
Order Class
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 Class
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
}
xaml code of the Invoice.xaml (for the simplicity only the necessary codes are shown. Model is the package of the Order and OrderItem classes.
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>
But I can achieve this without writing the xaml codes by writting the code in the Invoice.xaml.cs class where it is necessary.
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>
}
(including Binding each column to a property in OrderItem) Following codes are not necessary if the line dataGrid.ItemsSource = _order.OrderItems; is used.
xmlns:model="clr-namespace:Onion.Model"
<Window.Resources>
<model:Order x:Key="Order"/>
</Window.Resources>
DataContext="{Binding Source={StaticResource Order}}" ItemsSource="{Binding OrderItems}"
Can anyone point me how to overcome this problem.
Upvotes: 0
Views: 3978
Reputation: 31
When you populate your data, you then need to tell the framework that the data has been updated.
So from the Viewmodel code in your Setter of the collection, add a line that says RaisePropertyChanged("OrderItems") which is the Binding Source name you told the grid.
The workflow for this is:
Sorry I didn't have time to adapt your code. Hopefully this explains it well enough. Cheers.
Upvotes: 1
Reputation: 26213
Your grid is bound to the Order
static resource:
<Window.Resources>
<model:Order x:Key="Order"/>
</Window.Resources>
<DataGrid DataContext="{Binding Source={StaticResource Order}}" ...
In your event handler, you are creating a new Order
instance:
Order _order = new Order();
You are then calling a method that, you say, adds an OrderItem
to the OrderItems
collection in _order
. This is not the OrderItems
collection your DataGrid.ItemsSource
is bound to.
A simple fix might be to declare your Order
in the in the code behind and assign it to the DataContext
in the constructor:
private readonly Order _order = new Order();
public WindowName()
{
DataContext = _order;
}
Then remove the DataContext
binding from your DataGrid
(it will inherit the Window.DataContext
). Then you can remove Order _order = new Order()
from your event handler and use the instance field _order
instead.
Ideally, your event handler wouldn't be required and there would be an ICommand
in your Order
that would be bound to whatever button should add a new order.
Upvotes: 1