Kevin
Kevin

Reputation: 2688

Datagrid Update Checkbox IsChecked on DataGrid.Refresh()

I have a datagrid who's ItemsSource is a strongly typed IEnumerable object

In this datagrid, I have a checkbox column, a price column, a part name column, and a 'total selling for' column.

On checking the checkbox I need to update the total selling for column with the value in the price column.

This part I have working, however, how can I get the checkbox to remain checked when this happens?

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

uncommenting _CB.IsChecked = True does nothing

Here's the XAML for this datagrid:

                <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>

Upvotes: 0

Views: 1468

Answers (2)

Silvermind
Silvermind

Reputation: 5944

Here is an example of how it is more the WPF way, hopefully this gets you in the right direction. It has been a long time since I touched Visual Basic so please mind some missed conventions by me.

The 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>

Code Behind (Window Class and Part Class):

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

Upvotes: 1

paparazzo
paparazzo

Reputation: 45096

Pretty sure what is happening is this Event is fired before the update (set). So when you refresh you are getting the prior value. Assign the value of the CheckBox to the Property before you call refresh.

Upvotes: 1

Related Questions