mHelpMe
mHelpMe

Reputation: 6668

WPF Datagrid binding issues

I have a WPF application that contains a datagrid. I have an object called OrderBlock which contains a list called Orders. This list is bound to my datagrid.

The issue I have is a user imports the list of orders which is read into my list "Orders". This works fine & datagrid shows all the orders (let say 10 orders in total). The user then click a button to send the orders. The app then waits back from an outside application to see if any orders had an issues.

Let's say one order had an issue but the other 9 have been removed from my list. My datagrid is still showing all 10 orders? The OrderBlock has other properties apart from the list which do update on my UI, don't understand why the list is not?

If I step through my code and put a stop "OnPropertyChanged" in the setter of my list it does work.

One other thing to point out is that the one order that had an issue has a property called RejectReason which does change from null to "Some Error". Confussed.

Edit - code added

Two properties in OrderBlock object - OrderCountSuccess does update the list does not unless debugging.

 public int OrdersCountSuccess
    {
        get { return _ordersCountSuccess; }
        set { _ordersCountSuccess = value; OnPropertyChanged("OrdersCountSuccess"); }
    }


 public List<Order> Orders
    {
        get { return _orders; }
        set { _orders = value; OnPropertyChanged("Orders"); }
    }

OrderBlock object (in my view model) that contains the list of Orders

 public OrderBlock OrderBlockEntity
    {
        get
        {
            return _orderBlockEntity;
        }
        set
        {
            _orderBlockEntity = value;
            OnPropertyChanged("OrderBlockEntity");
        }
    }

This method is where orders are read into my list and then successfully displayed in my datagird

 private void ImportRun()
 {
     OrderBlockEntity = Qoe.GetOrders(_fileLocation);  
 }

This method is where the orders come back with any error information & the datagrid is not updating although I can see the list has changed

 private void SendRun()
    {
        OrderBlockEntity = Qoe.SendOrders(OrderBlockEntity);
    }

Xaml

<!-- Grid that contains the DataGrid which shows the list of orders -->
    <Grid Grid.Row="2" x:Name="GridOrders">
        <!-- The data grid to display orders-->
        <DataGrid DataContext="{Binding OrderBlockEntity}" 
                  x:Name="dataGridOrders" 
                  ItemsSource="{Binding Orders}"
                  Style="{StaticResource DataGridTemplate}"  
                  ColumnHeaderStyle="{StaticResource DG_ColumnHeader}"                                            
                  RowStyle="{StaticResource DG_Row}"
                  CellStyle="{StaticResource DG_Cell}"                                    
                  RowDetailsTemplate="{StaticResource DG_RowDetail}" 
                  RowHeaderStyle="{StaticResource DG_RowHeader}"
                  AutoGenerateColumns="False"
                  HorizontalAlignment="Stretch" 
                  VerticalAlignment="Stretch"
                  Background="Silver"
                  RowHeaderWidth="30"                      
                  Margin="25,5,20,15"                                            
                  RowDetailsVisibilityChanged="dataGridOrders_RowDetailsVisibilityChanged">                
            <DataGrid.RowHeaderTemplate>
                <DataTemplate>
                    <ToggleButton x:Name="RowHeaderToggleButton"                                        
                                  Click="RowHeaderToggleButton_Click"
                                  Cursor="Hand"/>
                    <DataTemplate.Triggers>
                        <DataTrigger Binding="{Binding DataContext.MultiID, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridRow}}}" Value="False">
                            <Setter TargetName="RowHeaderToggleButton" Property="Visibility" Value="Collapsed"/>
                        </DataTrigger>
                    </DataTemplate.Triggers>
                </DataTemplate>
            </DataGrid.RowHeaderTemplate>
            <DataGrid.Columns>
                <DataGridComboBoxColumn Header="Action">
                    <DataGridComboBoxColumn.ElementStyle>
                        <Style TargetType="ComboBox">
                            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.StatusList}"/>
                            <Setter Property="IsReadOnly" Value="True"/>
                            <Setter Property="SelectedValue" Value="{Binding StatusGood}"/>
                            <Setter Property="Background" Value="Silver"/>
                        </Style>
                    </DataGridComboBoxColumn.ElementStyle>
                    <DataGridComboBoxColumn.EditingElementStyle>
                        <Style TargetType="ComboBox">
                            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.StatusList}"/>
                            <Setter Property="IsReadOnly" Value="True"/>
                            <Setter Property="SelectedValue" Value="{Binding StatusGood, UpdateSourceTrigger=PropertyChanged}"/>
                            <Setter Property="Background" Value="Silver"/>
                        </Style>
                    </DataGridComboBoxColumn.EditingElementStyle>
                </DataGridComboBoxColumn>
                <DataGridTextColumn Header="Fund" Binding="{Binding Account}" IsReadOnly="True"/>
                <DataGridTextColumn Header="Security ID" Binding="{Binding Security.ID}" IsReadOnly="True"/>
                <DataGridTextColumn Header="ThinkFolio Security ID" Binding="{Binding Security.IDThinkFolio}" IsReadOnly="True"/>
                <DataGridTextColumn Header="Security Name" Binding="{Binding Security.Name}" IsReadOnly="True"/>
                <DataGridTextColumn Header="Buy/Sell" Binding="{Binding TransType}" IsReadOnly="True"/>
                <DataGridTextColumn Header="Quantity" Binding="{Binding OrderQunatity, StringFormat=\{0:N0\}}" IsReadOnly="False"/>
                <DataGridTextColumn Header="Currency" Binding="{Binding Security.Currency}" IsReadOnly="False"/>
                <DataGridTextColumn Header="Manager" Binding="{Binding FundManager}" IsReadOnly="True"/>
                <DataGridTextColumn Header="Dealing Desk" Binding="{Binding Dealer}" IsReadOnly="False"/>
                <DataGridTextColumn Header="Order Reason" Binding="{Binding OrderReason}" IsReadOnly="False"/>
                <DataGridTextColumn Binding="{Binding RejectReason}" IsReadOnly="True">
                    <DataGridTextColumn.Header>
                        <TextBlock Text="{Binding DataContext.ColumnHeadInfo, RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}}"/>
                    </DataGridTextColumn.Header>
                </DataGridTextColumn>
                <DataGridTextColumn Header="Comments" Binding="{Binding Comments}" IsReadOnly="False" Width="*"/>
            </DataGrid.Columns>
        </DataGrid>            
    </Grid>

Upvotes: 0

Views: 523

Answers (2)

eran otzap
eran otzap

Reputation: 12533

The reason why PropertyChanged event in the setter works is because it re-sets the entire ItemsSource , so that's one way you can approach that issue , a more effective way is to use an ObservableCollection , your ItemsControl listens to INotifyCollectionChanged.CollectionChanged event and updates the ItemsContainerGenerator which is in charge of the actual UI elements for each one of your items.

Upvotes: 0

Bere
Bere

Reputation: 46

Use ObservableCollection instead of List.

Upvotes: 2

Related Questions