【问题标题】:WPF Datagrid binding issuesWPF Datagrid 绑定问题
【发布时间】:2014-01-07 14:24:01
【问题描述】:

我有一个包含数据网格的 WPF 应用程序。我有一个名为 OrderBlock 的对象,其中包含一个名为 Orders 的列表。此列表绑定到我的数据网格。

我遇到的问题是用户将订单列表导入到我的“订单”列表中。这很好用,数据网格显示所有订单(比如说总共 10 个订单)。然后用户点击一个按钮来发送订单。然后,该应用程序会等待外部应用程序返回,以查看是否有任何订单有问题。

假设一个订单有问题,但其他 9 个订单已从我的列表中删除。我的数据网格仍然显示所有 10 个订单? OrderBlock 除了列表之外还有其他属性会在我的 UI 上更新,不明白为什么列表没有?

如果我单步执行我的代码并在列表的设置器中停止“OnPropertyChanged”,它确实有效。

要指出的另一件事是,有问题的一个订单有一个名为 RejectReason 的属性,该属性确实从 null 更改为“Some Error”。困惑。

编辑 - 添加代码

OrderBlock 对象中的两个属性——OrderCountSuccess 不会更新列表,除非调试。

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


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

OrderBlock 对象(在我的视图模型中)包含订单列表

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

此方法是订单被读入我的列表,然后成功显示在我的数据网格中

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

此方法是订单返回任何错误信息的地方,尽管我可以看到列表已更改,但数据网格并未更新

 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>

【问题讨论】:

  • 据我所知,您的 OrderBlock 不会触发,因为它没有实现 INotifyCollectionChanged - 因为 OrderBlock 是您的 Orders 集合,它应该实现这一点。不过,我认为使用 ObservableCollection 会更好,请查看@user1729313 答案! :)

标签: c# wpf datagrid


【解决方案1】:

使用 ObservableCollection 代替 List。

【讨论】:

  • ...别忘了实现 INotifyCollectionChanged
  • @Eisenhorn 他应该在哪里实施 INotifyCollectionChanged ? ObservableCollection 实现 INotifyCollectionChanged 。
  • @eranotzap:当然,你是对的。但是,集合中的项目必须实现 INotifyPropertyChanged。
  • 我认为他实际上可以创建自己的集合,只要他实现 INotifyCollectionChanged 并在需要时提出它。
【解决方案2】:

setter 中的 PropertyChanged 事件起作用的原因是它重新设置了整个 ItemsSource , 所以这是你可以解决这个问题的一种方法,更有效的方法是使用 ObservableCollection , 您的 ItemsControl 会侦听 INotifyCollectionChanged.CollectionChanged 事件并更新 ItemsContainerGenerator,它负责您的每个项目的实际 UI 元素。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-10
    • 2011-08-15
    • 1970-01-01
    • 2011-04-10
    • 2023-04-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多