【问题标题】:Datagrid Update Checkbox IsChecked on DataGrid.Refresh()DataGrid.Refresh() 上的 Datagrid 更新复选框 IsChecked
【发布时间】:2012-04-05 08:16:48
【问题描述】:

我有一个数据网格,它的 ItemsSource 是一个强类型的 IEnumerable 对象

在这个数据网格中,我有一个复选框列、一个价格列、一个零件名称列和一个“总销售额”列。

选中复选框后,我需要使用价格列中的值更新列的总销售额。

这部分我正在工作,但是,当发生这种情况时,如何让复选框保持选中状态?

Private Sub UpdateSellFor(sender As System.Object, e As System.Windows.RoutedEventArgs)
    Dim _CB As CheckBox = DirectCast(sender, CheckBox)
    Dim _ID As Integer = _CB.Tag
    Dim _PP = DirectCast(DG_PartsToSelect.CurrentItem, PartTyping).PartPrice
    If _CB.IsChecked Then
        DG_PartsToSelect.CurrentItem.PartSellingFor = DirectCast(DG_PartsToSelect.CurrentItem, PartTyping).PartPrice
        DG_PartsToSelect.Items.Refresh()
    Else

    End If
    '_CB.IsChecked = True
End Sub

取消注释 _CB.IsChecked = True 什么都不做

这是此数据网格的 XAML:

                <DataGrid IsReadOnly="True" AutoGenerateColumns="False" Grid.Column="1" HorizontalAlignment="Stretch" Margin="3" Name="DG_PartsToSelect" VerticalAlignment="Stretch">
                    <DataGrid.Columns>
                        <DataGridTextColumn Header="Part ID" Binding="{Binding PartID}" />
                        <DataGridTemplateColumn Header="Part Name">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding PartName}" Cursor="Hand" MouseDown="PartDetails" Tag="{Binding PartID}" ToolTip="Click to See the Part Details" />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTextColumn Header="Selling For" Binding="{Binding PartPrice, StringFormat='{}{0:C}'}" />
                        <DataGridTemplateColumn Header="Part Options">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Image Cursor="Hand" Height="22" Name="options" Tag="{Binding PartID}" MouseDown="PartOptions" Source="/v2Desktop;component/Images/Application.png" ToolTip="Select Part Options" />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTemplateColumn Header="Sell This Part">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <CheckBox Name="SelectedPart" Tag="{Binding PartID}" ToolTip="Select This Part" Click="UpdateSellFor" />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTextColumn Header="Total Selling For" Binding="{Binding PartSellingFor, StringFormat='{}{0:C}'}" />
                    </DataGrid.Columns>
                </DataGrid>

【问题讨论】:

  • 只是猜测,但您是否在 CellTemplate 的 TemplateColum 中意外创建了 TextBox,否则请提供一些 xaml。想一想;请务必提供 xaml。
  • 复选框是一个模板,是的,但不是 Total Selling For
  • 大多数情况下发生的情况是,没有例如 CellEditingTemplate 的 CellTemplate 中的复选框在检查为 false 时重置,因为查看您的方法让我假设您没有对中的复选框进行绑定你的xml。
  • 不是正式的没有。但是 .Tag 是绑定的
  • 我建议您将 IsCalculated DependencyProperty 添加到 Binded 类并将 CheckBox 绑定到该类。在 PropertyChangedCallbackHandler 中,您可以使用 DependencyObject d 作为您的项目来更新该行的价格。如果你想要一个例子,请告诉我。

标签: .net wpf vb.net datagrid wpfdatagrid


【解决方案1】:

很确定发生了什么是在更新(设置)之前触发了此事件。因此,当您刷新时,您将获得先前的值。在调用 refresh 之前将 CheckBox 的值分配给 Property。

【讨论】:

  • 哪个事件?设置什么属性?请查看我发布的代码。它包含在复选框的“单击”事件中发生的所有事情
  • 没错,然后点击事件还有更多的事情发生。检查 _cb 上的 Set - 它是否被调用以及传递了什么值?
  • “检查集合”???只是不确定你的意思。当我调试代码时,复选框是整个...
  • 您没有绑定
【解决方案2】:

这是一个示例,说明它更像是 WPF 方式,希望这能让您朝着正确的方向前进。 我已经很久没有接触 Visual Basic,所以请注意我错过的一些约定。

Xaml:

    <DataGrid AutoGenerateColumns="False" HorizontalAlignment="Stretch" Margin="3" x:Name="DG_PartsToSelect" VerticalAlignment="Stretch" ItemsSource="{Binding}">
      <DataGrid.Columns>
        <DataGridTextColumn Header="ID" Binding="{Binding Path=ID}" IsReadOnly="True" />
        <DataGridTextColumn Header="Name" Binding="{Binding Path=Name}" IsReadOnly="True"/>
        <DataGridTemplateColumn Header="Selling For">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <TextBlock Text="{Binding Path=SellingPrice, StringFormat='{}{0:C}', Mode=OneWay}"/>
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
          <DataGridTemplateColumn.CellEditingTemplate>
            <DataTemplate>
              <TextBox Text="{Binding Path=SellingPrice, UpdateSourceTrigger=PropertyChanged}"/>
            </DataTemplate>
          </DataGridTemplateColumn.CellEditingTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Part Options">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <Border Background="#88BBFF" Cursor="Hand" Height="22" ToolTip="Select Part Options" MouseUp="PartOptions_MouseUp"/><!--just for testing with no image-->
              <!--<Image Cursor="Hand" Height="22" Source="" ToolTip="Select Part Options" MouseDown="PartOptions_MouseDown"/>-->
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTemplateColumn Header="Sell This Part">
          <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
              <CheckBox Name="SelectedPart" IsChecked="{Binding Path=IsCalculated, UpdateSourceTrigger=PropertyChanged}" ToolTip="Select This Part"  />
            </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn IsReadOnly="True" Header="Total Selling For" Binding="{Binding Path=TotalSellingFor, StringFormat='{}{0:C}'}" />
      </DataGrid.Columns>
    </DataGrid>

代码后面(窗口类和部件类):

Imports System.ComponentModel
Imports System.Collections.ObjectModel

Class MainWindow

  Dim Parts As ObservableCollection(Of Part)

  Private Sub PartOptions_MouseUp(sender As System.Object, e As System.Windows.Input.MouseButtonEventArgs)
    If DG_PartsToSelect.SelectedItem Is Nothing Then
      Exit Sub
    End If
    Dim selectedPart = DirectCast(DG_PartsToSelect.SelectedItem, Part)
    MessageBox.Show(String.Format("The name = {0}", selectedPart.Name), String.Format("The id = {0}", selectedPart.ID), MessageBoxButton.OK, MessageBoxImage.Information)
  End Sub

  Public Sub New()
    InitializeComponent()
    Parts = New ObservableCollection(Of Part)
    Parts.Add(New Part(1, "test", 100D))
    Parts.Add(New Part(2, "Name here", 99.99D))
    Parts.Add(New Part(3, "What", 23.19D))
    DG_PartsToSelect.DataContext = Parts
  End Sub
End Class

Public Class Part : Implements INotifyPropertyChanged

  Private IDField As Integer
  Public Property ID() As Integer
    Get
      Return IDField
    End Get
    Set(ByVal value As Integer)
      IDField = value
      OnPropertyChanged("ID")
    End Set
  End Property

  Private NameField As String
  Public Property Name() As String
    Get
      Return NameField
    End Get
    Set(ByVal value As String)
      NameField = value
      OnPropertyChanged("Name")
    End Set
  End Property

  Private SellingPriceField As Decimal
  Public Property SellingPrice() As Decimal
    Get
      Return SellingPriceField
    End Get
    Set(ByVal value As Decimal)
      SellingPriceField = value
      OnPropertyChanged("SellingPrice")
      IsCalculatedField = False
      OnPropertyChanged("IsCalculated")
    End Set
  End Property

  Private IsCalculatedField As Boolean
  Public Property IsCalculated() As Boolean
    Get
      Return IsCalculatedField
    End Get
    Set(ByVal value As Boolean)
      If (IsCalculatedField And Not value) Then
        Exit Property
      End If
      IsCalculatedField = value
      UpdateTotalPrice()
    End Set
  End Property

  Private TotalSellingForField As Decimal
  Public Property TotalSellingFor() As Decimal
    Get
      Return TotalSellingForField
    End Get
    Set(ByVal value As Decimal)
      TotalSellingForField = value
    End Set
  End Property

  Public Event PropertyChanged As PropertyChangedEventHandler _
        Implements INotifyPropertyChanged.PropertyChanged

  Public Sub New(id As Integer, name As String, sellingPrice As Decimal)
    IDField = id
    NameField = name
    SellingPriceField = sellingPrice
  End Sub

  Sub UpdateTotalPrice()
    ''This will multiply the price of the SellingPriceValue times 2 and put it in the TotalSellingForField
    TotalSellingForField = SellingPriceField * 2
    OnPropertyChanged("TotalSellingFor")
  End Sub

  Sub OnPropertyChanged(propertyName As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName))
  End Sub

End Class

【讨论】:

  • 很抱歉,我在这一行已经收到错误消息:Public Event PropertyChanged As ComponentModel.PropertyChangedEventHandler 在 INotifyPropertyChanged 上实现 INotifyPropertyChanged.PropertyChanged,没有任何建议
  • 声明 INotifyPropertyChanged 未定义
  • 没关系,我错过了:实现 INotifyPropertyChanged... DOH... 见 NOOB
  • 所以你让我朝着正确的方向前进。解决方案实际上比这简单得多。我确实需要在复选框本身上绑定 IsChecked,我在 PartsTyping 类中创建了一个新属性为 boolean = false,然后在 UpdateSellFor 中,我只需将该字段的值更改为 True(如果再次单击,则返回为 false )
  • 你知道是否有办法奖励多个解决方案作为答案吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-20
  • 2015-10-22
  • 2018-04-09
  • 1970-01-01
  • 1970-01-01
  • 2013-02-11
  • 1970-01-01
相关资源
最近更新 更多