Click here to Skip to main content
15,882,209 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
Good evening.
I have a DataGrid in WPF.
I want, when moue cursor moves to bottom of each row, a plus sign appears at the bottom of that row.
So then the user can click on it, and a new row inserted there.
Anybody has idea that what is approach for this scenario ?

UPDATED: Please check the attachment picture.
Adding Plus To Data Grid — Postimages[^]

What I have tried:

I don't have any clue for this.
Updated 11-Jan-24 2:28am
[no name] 10-Jan-24 19:40pm    
If there's a keyboard, a number of "key combinations" are typically used: e.g. down arrow; ctrl+N; to add a new "blank" record; for saving or discarding: F2; Esc. Otherwise, there's a "new" button or "add" button. And save / update, and cancel buttons. Or you pop up a form and avoid the whole debate.
Sh.H. 11-Jan-24 8:24am    
@Gerry Schmitz
Thanks for answer. Please check my question again. I need to find the way of how a plus button appears when the mouse moves to bottom of a cell.
I updated the question with a picture. please see the picture. Thanks.
[no name] 12-Jan-24 12:31pm    
The "mouse cursor" doesn't "move to the bottom"; it can only "move over" and "hover". You have not selected anything. There is no evidence of intent to "insert". The context is "wrong" and confusing. And wouldn't work in a "touch" application.

There is not much information to go on, I will however implement something like my code below. This is in no way a full solution, only a pointer for you in the right direction, you need to modify the code to work for you -

Imports System.Windows.Controls.Primitives

Class MainWindow
    Private Sub myDataGrid_MouseMove(sender As Object, e As MouseEventArgs)
        Dim dataGrid As DataGrid = TryCast(sender, DataGrid)

        If dataGrid IsNot Nothing Then
            Dim hitTestResult As HitTestResult = VisualTreeHelper.HitTest(dataGrid, e.GetPosition(dataGrid))

            If hitTestResult IsNot Nothing AndAlso hitTestResult.VisualHit IsNot Nothing Then
                Dim row As DataGridRow = TryCast(DataGridRow.GetRowContainingElement(hitTestResult.VisualHit), DataGridRow)

                If row IsNot Nothing Then
                End If
            End If
        End If
    End Sub

    Private Sub ShowPlusIconForRow(row As DataGridRow)
        'Add your logic to show the plus sign or icon at the bottom right of the row...
        'You can use something like a Popup, Tooltip, or any other control that will work for you...
        'As an example...
 row.ToolTip = "Click to add a row below this one"
        AddHandler row.MouseLeftButtonDown, AddressOf AddRowOnClick
    End Sub

    Private Sub AddRowOnClick(sender As Object, e As MouseButtonEventArgs)
        Dim clickedRow As DataGridRow = TryCast(sender, DataGridRow)

        If clickedRow IsNot Nothing Then
            'Add a new row below the clicked row...
            Dim newRow As New YourDataRowType() 
'Replace YourDataRowType with the actual type of your data used...
            Dim rowIndex As Integer = myDataGrid.Items.IndexOf(clickedRow.Item)
            myDataGrid.Items.Insert(rowIndex + 1, newRow)
        End If
    End Sub
End Class
Share this answer
Sh.H. 12-Jan-24 15:55pm    
@Andre Oosthuizen
Thanks foe implementing.
Did you check the picture I attached to the question?
The code you implemented, does not work as I explained.
In your code, the action starts in every place of a cell.
But what I need is only on the divider on rows.
I mean the plus icon appears when mouse hover on the divider of rows (between two rows.)
I found a solution.
Below code works perfect. However, I think there is better way for this scenario. For example I think there could be a way to use CallBack and Filtering. But I do not have any idea.
So please kindly help me to make a better code.
I notice again that this code works perfect.

<Window x:Class="MainWindow"
        Title="MainWindow" Height="450" Width="800">
        <DataGrid x:Name="DGCheckingProjector" 
                <DataGridTextColumn Header="" IsReadOnly="True" Width="2*" Binding="{Binding IndexNo}"/>
                <DataGridTextColumn Header="TheText" IsReadOnly="False" Width="26*" Binding="{Binding TheText}"/>
                <DataGridTextColumn Header="Dubber" IsReadOnly="False" Width="12*" Binding="{Binding DubberName}"/>
                <DataGridTextColumn Header="Character" IsReadOnly="False" Width="12*" Binding="{Binding CharacterName}"/>
                <DataGridTextColumn Header="Gender" IsReadOnly="False" Width="10*" Binding="{Binding GenderOfCharacter}"/>
        <TextBlock x:Name="tbSTATUS" HorizontalAlignment="Left" Margin="114,196,0,0" TextWrapping="Wrap" Text="" FontSize="26" Background="White" VerticalAlignment="Top" Height="106" Width="297"/>

Class MainWindow
    Public Class SubtitleClass
        Public Property FlagOfSubInVideo As New Boolean
        Public Property IndexNo As Integer
        Public Property StartingTimeCode As String
        Public Property EndingTimeCode As String
        Public Property TheText As String
        Public Property DubberName As String
        Public Property CharacterName As String
        Public Property GenderOfCharacter As String
    End Class
    Public MySub As New System.Collections.ObjectModel.ObservableCollection(Of SubtitleClass)
    Private UpperRowIndexToInsert As String = Nothing
    Private LowerRowIndexToInsert As String = Nothing
    Sub New()

        Dim Fname As String(), Lname As String(), Cname As String()
        ReDim Preserve Fname(10), Lname(10), Cname(10)
        Fname(1) = "Ali" : Fname(2) = "Morteza" : Fname(3) = "Reza" : Fname(4) = "Kazem" : Fname(5) = "Hassan" : Fname(6) = "Hossein" : Fname(7) = "Farhad" : Fname(8) = "Shervin" : Fname(9) = "" : Fname(10) = "Mohammad"
        Lname(1) = "Alavi" : Lname(2) = "Ghalichi" : Lname(3) = "Hosseini" : Lname(4) = "Kazemi" : Lname(5) = "Kordani" : Lname(6) = "Tehrani" : Lname(7) = "Moghadam" : Lname(8) = "Haddadi" : Lname(9) = "" : Lname(10) = "Karimian"
        Cname(1) = "Arnold" : Cname(2) = "Richard" : Cname(3) = "Big Man" : Cname(4) = "Agent Smith" : Cname(5) = "Prisoner" : Cname(6) = "Mr. Anderson" : Cname(7) = "Kenneth Williams" : Cname(8) = "Eddie Morphy" : Cname(9) = "William Marchoma" : Cname(10) = "Queentin Tarantino"

        For I As Integer = 1 To 100
            MySub.Add(New SubtitleClass With {
                .FlagOfSubInVideo = Int(2 * Rnd()),
                .IndexNo = Int((1255) * Rnd() + 1) + I,
                .StartingTimeCode = "12:34:56:789",
                .EndingTimeCode = "21:43:65:987",
                .TheText = $"This is the Text of Subtitle number {I}",
                .DubberName = Fname(Int(10 * Rnd() + 1)) & " " & Lname(Int(10 * Rnd() + 1)),
                .CharacterName = Cname(Int(10 * Rnd() + 1)),
                .GenderOfCharacter = If((Int(2 * Rnd())), "Male", "Female")
        Next I

        DGCheckingProjector.ItemsSource = MySub

        btnPLUS.Visibility = Visibility.Hidden

    End Sub
    Private Sub DGCheckingProjector_PreviewMouseMove(sender As Object, e As MouseEventArgs) Handles DGCheckingProjector.PreviewMouseMove
        Dim MyDataGrid As DataGrid = TryCast(sender, DataGrid)
        Dim pt As Point = e.GetPosition(MyDataGrid)
        If MyDataGrid IsNot Nothing Then
            Dim hitTestResult As HitTestResult = VisualTreeHelper.HitTest(MyDataGrid, New Point(0, pt.Y))
            Dim hitTestResultU As HitTestResult = VisualTreeHelper.HitTest(MyDataGrid, New Point(0, pt.Y - 10))
            Dim hitTestResultD As HitTestResult = VisualTreeHelper.HitTest(MyDataGrid, New Point(0, pt.Y + 10))
            Dim row As DataGridRow = If(hitTestResult IsNot Nothing, TryCast(DataGridRow.GetRowContainingElement(hitTestResult.VisualHit), DataGridRow), Nothing)
            Dim rowU As DataGridRow = If(hitTestResultU IsNot Nothing, TryCast(DataGridRow.GetRowContainingElement(hitTestResultU.VisualHit), DataGridRow), Nothing)
            Dim rowD As DataGridRow = If(hitTestResultD IsNot Nothing, TryCast(DataGridRow.GetRowContainingElement(hitTestResultD.VisualHit), DataGridRow), Nothing)
            Dim bool As Boolean = False
            If hitTestResult IsNot Nothing Then
                If hitTestResult.VisualHit.DependencyObjectType.Name = "Border" Then
                    If row IsNot Nothing Then
                        If rowU IsNot Nothing And rowD IsNot Nothing Then
                            If String.Equals(row.GetIndex, rowU.GetIndex) Or String.Equals(row.GetIndex, rowD.GetIndex) Then
                                bool = True
                                UpperRowIndexToInsert = rowU.GetIndex
                                LowerRowIndexToInsert = rowD.GetIndex
                            End If
                        ElseIf rowD Is Nothing Then
                            If row.GetIndex = MyDataGrid.Items.Count - 1 Then UpperRowIndexToInsert = rowU.GetIndex : LowerRowIndexToInsert = Nothing : bool = True
                        End If
                    End If
                End If
            End If
            If hitTestResultU IsNot Nothing And Not bool Then
                If hitTestResultU.VisualHit.DependencyObjectType.Name = "Rectangle" Then
                    If row IsNot Nothing Then
                        If row.GetIndex = 0 Then
                            UpperRowIndexToInsert = Nothing
                            LowerRowIndexToInsert = rowD.GetIndex
                            bool = True
                            UpperRowIndexToInsert = row.GetIndex - 1
                            LowerRowIndexToInsert = row.GetIndex
                            bool = True
                        End If
                    End If
                End If
            End If
            If bool Then
                btnPLUS.Visibility = Visibility.Visible
                tbSTATUS.Text = "Beyne " & If(UpperRowIndexToInsert, "Null") & " & " & If(LowerRowIndexToInsert, "Null")
                btnPLUS.Margin = New Thickness(btnPLUS.Margin.Left, -btnPLUS.RenderSize.Height / 2, btnPLUS.Margin.Right, btnPLUS.Margin.Bottom)
                Dim myTranslateTransform As TranslateTransform = New TranslateTransform
                If rowD IsNot Nothing Then
                    myTranslateTransform.Y = rowD.TranslatePoint(New Point(0, 0), DGCheckingProjector).Y
                ElseIf row IsNot Nothing Then
                    myTranslateTransform.Y = row.TranslatePoint(New Point(0, 0), DGCheckingProjector).Y + row.RenderSize.Height
                End If
                btnPLUS.RenderTransform = myTranslateTransform
                btnPLUS.Visibility = Visibility.Hidden
                tbSTATUS.Text = ""
            End If
        End If
    End Sub
    Private Sub BtnPLUS_Click(sender As Object, e As RoutedEventArgs) Handles btnPLUS.Click
        Dim newRow As New SubtitleClass With {
                    .FlagOfSubInVideo = Int(2 * Rnd()),
                    .IndexNo = "500",
                    .StartingTimeCode = "11:22:33:456",
                    .EndingTimeCode = "44:55:66:789",
                    .TheText = $"This is new item",
                    .DubberName = "M",
                    .CharacterName = "N",
                    .GenderOfCharacter = If((Int(2 * Rnd())), "Male", "Female")
        If LowerRowIndexToInsert IsNot Nothing Then
            MySub.Insert(LowerRowIndexToInsert, newRow)
            DGCheckingProjector.ScrollIntoView(DGCheckingProjector.Items(DGCheckingProjector.Items.Count - 1))
        End If
    End Sub
End Class
Share this answer

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900