Custom function on wpf datagrid

Hello,

I need a datagrid with 7 columns, the first one contain the players name, the other 5 can be only 0 or 1. the latest one is the sum of the prev one. Every row is a player and score .

The latest column should update itself when the 5 score cell change.

When select one cell on the 5 score column it should be possible to enter only 0 or 1, and after he did it should no need to press enter or tab to commit and jump to the next one. It the cell is the latest score for a player it should jump on the first score on the next player.

When user write one cell background should be change to red, and green for 1.

Is it possible to do with the sfDatagrid?

Regards


19 Replies

SJ Sathiyathanam Jeyakumar Syncfusion Team May 9, 2023 04:59 PM UTC

Hi Halcyon Security,

We are currently working to achieve your requirements from our end. We will provide further details on May 11, 2023.

Regards,

Sathiyathanam



HS Halcyon Security May 10, 2023 12:49 PM UTC

Thanks, I have another question; to display data like in this pictures, how should I organize the data of the game?



 



SJ Sathiyathanam Jeyakumar Syncfusion Team May 11, 2023 11:04 AM UTC

Halcyon Security,

Your requirement to show the playing details in the DataGrid, as per the screenshots, can be achieved by using the MergedCells and concept. The MatchTotal and Total column values will be updated by using the GridUnBoundColumn.

By using the QueryCoveredRange concept, we can merge cells. Please refer to the code snippets below.

dataGrid.QueryCoveredRange += dataGrid_QueryCoveredRange;

void dataGrid_QueryCoveredRange(object sender, GridQueryCoveredRangeEventArgs e)

{

    if(e.GridColumn.MappingName == "PlayerName" || e.GridColumn.MappingName == "Total")

    {

        var range = GetRange(e.GridColumn, e.RowColumnIndex.RowIndex, e.RowColumnIndex.ColumnIndex, e.Record);

 

        if (range == null)

            return;

 

        // You can know that the range is already exist in Covered Cells by IsInRange method.

 

        if (!dataGrid.CoveredCells.IsInRange(range))

        {

            e.Range = range;

            e.Handled = true;

        }

    }

}

 


By utilizing the concepts of GridUnbondColumn and QueryUnboundColumnValue, we can update the calculation for MatchTotal and Total. We would like to inform you that the MatchTotal value will be updated using the GridUnBoundColumn Expression. However, we are unable to directly update the Total column using the Expression, so we are using QueryUnboundColumnValue to calculate the Total values. Therefore, for this Total implementation, we have introduced some global fields and without this event and customization, we are not able to calculate the Total value. Please refer to the code snippets below.

<Grid>

    <syncfusion:SfDataGrid x:Name="dataGrid"

                            AutoGenerateColumns="False"

                            ColumnSizer="Star"

                            CellStyleSelector="{StaticResource cellstyleSelector}"

                            SelectionUnit="Cell"

                            ShowGroupDropArea="True"

                            ItemsSource="{Binding PlayerDetails}">

        <syncfusion:SfDataGrid.Columns>

            <syncfusion:GridTextColumn MappingName="PlayerName"  />

            <syncfusion:GridNumericColumn MappingName="P1" NumberDecimalDigits="0" AllowEditing="True" />

            <syncfusion:GridNumericColumn       MappingName="P2" NumberDecimalDigits="0" AllowEditing="True"/>

            <syncfusion:GridNumericColumn       MappingName="P3" NumberDecimalDigits="0" AllowEditing="True"/>

            <syncfusion:GridNumericColumn       MappingName="P4" NumberDecimalDigits="0" AllowEditing="True"/>

            <syncfusion:GridNumericColumn       MappingName="P5" NumberDecimalDigits="0" AllowEditing="True"/>

            <syncfusion:GridUnBoundColumn MappingName="MatchTotal"  Expression="P1+P2+P3+P4+P5"/>

            <syncfusion:GridUnBoundColumn MappingName="Total" />

        </syncfusion:SfDataGrid.Columns>

    </syncfusion:SfDataGrid>

</Grid>

 

dataGrid.QueryUnboundColumnValue += dataGrid_QueryUnboundColumnValue;

 

int sum = 0;

string playerName = string.Empty;

private void dataGrid_QueryUnboundColumnValue(object sender, GridUnboundColumnEventsArgs e)

{

    if(e.Column.MappingName == "Total")

    {

        var record = e.Record as Model;

        var viewModel = this.dataGrid.DataContext as ViewModel;

        if (playerName == "")

            playerName = record.PlayerName;

        if (playerName != record.PlayerName)

        {

            sum = 0;

            playerName = record.PlayerName;

        }

        if (sum > 0)

        {

            e.Value = sum;

            return;

        }

        var list = viewModel.PlayerDetails.Where(x => x.PlayerName == record.PlayerName);

        foreach (var model in list)

        {

            if (record.PlayerName == model.PlayerName)

            {

                sum += model.P1 + model.P2 + model.P3 + model.P4 + model.P5;

            }

        }

        e.Value = sum;

    }

           

}

}



Additionally, we have customized the renderer to only accept 0's and 1's in a NumericColumn, and restricted selection navigation when the Enter or Tab key is pressed.

        public MainWindow()

        {

            InitializeComponent();

            dataGrid.CellRenderers.Remove("Numeric");

            dataGrid.CellRenderers.Add("Numeric",new GridCellNumericRendererExt(this.dataGrid));

        }

 

public class GridCellNumericRendererExt : GridCellNumericRenderer

{

    public SfDataGrid DataGrid { get; set; }

    public GridCellNumericRendererExt(SfDataGrid dataGrid)

    {

        DataGrid = dataGrid;

    }

    protected override void OnEditElementLoaded(object sender, RoutedEventArgs e)

    {

        base.OnEditElementLoaded(sender, e);

        var uiElement = ((DoubleTextBox)sender);

        uiElement.KeyDown += UiElement_KeyDown;

    }

 

    private void UiElement_KeyDown(object sender, KeyEventArgs e)

    {

        // Here we have handled the 0 key  and 1 key in NumericColumn editing case.

        if (e.Key != Key.D0 && e.Key != Key.D1)

            e.Handled = true;

    }

    protected override bool ShouldGridTryToHandleKeyDown(KeyEventArgs e)

    {

        // Here we have handled the Enter key  and Tab key in NumericColumn to restrict the navigation.

 

        if (e.Key == Key.Enter || e.Key == Key.Tab)

        {

            return false;

        }

        else

        {

            return base.ShouldGridTryToHandleKeyDown(e);

        }

    }

 

}


By using the CellStyleSelector, you can color the cells based on their values. Please refer to the code snippets below.

<Grid>

    <syncfusion:SfDataGrid x:Name="dataGrid"

                            AutoGenerateColumns="False"

                            ColumnSizer="Star"

                            CellStyleSelector="{StaticResource cellstyleSelector}"

                            SelectionUnit="Cell"

                            ShowGroupDropArea="True"

                            ItemsSource="{Binding PlayerDetails}">

 

 

 

public class CellStyleSelector : StyleSelector

{

    public override Style SelectStyle(object item, DependencyObject container)

    {

        var model = item as Model;

        var gridCell = container as GridCell;

        var dataGrid = (SfDataGrid)gridCell.ColumnBase.GridColumn.GetType().GetProperty("DataGrid", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(gridCell.ColumnBase.GridColumn);

        if (gridCell.ColumnBase.GridColumn.MappingName != "PlayerName" && gridCell.ColumnBase.GridColumn.MappingName != "Total"

            && gridCell.ColumnBase.GridColumn.MappingName != "MatchTotal")

        {

            //Here we have reteurn the different cellstyle based on the P1-P5 Cells.

            object displayValue  = dataGrid.View.GetPropertyAccessProvider().GetFormattedValue(model, gridCell.ColumnBase.GridColumn.MappingName);

            int val = Int32.Parse(displayValue.ToString());

            if(val == 0)

            {

                return Application.Current.Resources["cellStyle"] as Style;

            }

            else

            {

                return Application.Current.Resources["cellStyle1"] as Style;

 

            }

        }

        return base.SelectStyle(item, container);

    }

}



We are a little unclear about your selection requirement. "If the cell is the latest score for a player, it should jump to the first score for the next player." Could you please provide more details about this requirement? This will be helpful in further investigation.



SJ Sathiyathanam Jeyakumar Syncfusion Team May 11, 2023 11:09 AM UTC

Halcyon Security,

We forgot to attach the sample. Please find it in the attachment below.


Attachment: SfDataGridDemo_a936a417.zip


HS Halcyon Security May 11, 2023 01:43 PM UTC

Hello,

user should be place the focus on a cell( only data in P1-5 should be editable), and then he should use only keyboard to insert edit points.

So after he press 1 or 0 the cell should be commited without press enter and focus must go to the next point cell.

If he's editing P5 of a row, next  focused cell should be P1 of the next row.

Let me know if it's clear or not.

Regards



SJ Sathiyathanam Jeyakumar Syncfusion Team May 12, 2023 10:35 AM UTC

Halcyon Security,

In DataGrid by default the cell will goes to the editing when we are pressing the F2 key.By pressing the F2 key in cells P1-P5 then you can initiate the editing.And we have disable the MouseClick editing for P1-P5 cells in a CurrentCellBeginEdit evet by using the IsKeyDown property. And when you type 0 or 1 in a P1-P5 cell, it will be automatically committed and move to the next adjacent cell. If the current cell is on P5, then after editing P5, the current cell will be moved to the first cell of the next row.


private void DataGrid_CurrentCellBeginEdit(object sender, CurrentCellBeginEditEventArgs e)

{

    var dataContext = this.dataGrid.DataContext as ViewModel;

    //Used to disble the mouse click editing in SfDataGrid. Now the user only can edit the column by using the any key ie. F2 key.

    if (!dataContext.IskeyDown)

        e.Cancel = true;

    dataContext.IskeyDown = false;

 

}

 

public class GridCellSelectionControllerExt : GridCellSelectionController

{

    public GridCellSelectionControllerExt(SfDataGrid dataGrid ) : base(dataGrid)

    {

 

    }

    protected override void ProcessKeyDown(KeyEventArgs args)

    {

//Here we have set the IsKeyDown property to true.By using this API we have go to edit mode for SfDataGrid

 

        (this.DataGrid.DataContext as ViewModel).IskeyDown = true;

        base.ProcessKeyDown(args);

    }

 

}


Below code snippets used to move the current cell when editing completed.


private void DataGrid_CurrentCellEndEdit(object sender, CurrentCellEndEditEventArgs e)

{

    //Here we have called the UpdateDataRow to update the Total column when we edit the P1-P5 cells.

    //And also reset the total cell value calculation customization to update the Total value properly.

    playerName = "";

    sum = 0;

    for(int i=1; i<= e.RowColumnIndex.RowIndex; i++)

    {

        this.dataGrid.UpdateDataRow(i);

    }

    MoveSelection(e.RowColumnIndex);

}

private void MoveSelection(RowColumnIndex rowColumnIndex)

{

    var col = this.dataGrid.Columns[rowColumnIndex.ColumnIndex];

    RowColumnIndex rowColumnIndex1 = new RowColumnIndex();

    if (col.MappingName == "P5")

    {

        rowColumnIndex1.RowIndex = (rowColumnIndex.RowIndex + 1) >  this.dataGrid.View.Records.Count - 1  ? 1 : rowColumnIndex.RowIndex + 1;

        var column = this.dataGrid.Columns["P1"];

        rowColumnIndex1.ColumnIndex = this.dataGrid.ResolveToScrollColumnIndex(this.dataGrid.Columns.IndexOf(column));

    }

    else

    {

        rowColumnIndex1.ColumnIndex = rowColumnIndex.ColumnIndex + 1;

        rowColumnIndex1.RowIndex = rowColumnIndex.RowIndex;

    }

    this.dataGrid.MoveCurrentCell(rowColumnIndex1);

}




Attachment: SfDataGridDemo_da52630.zip


HS Halcyon Security May 12, 2023 11:08 AM UTC

I'm sorry, this is not the exactly behaviour that I'm looking for:

-In your example user can digit any number, but I need only 0 and 1 (single digit) be allowed

- In your example to start edit user need to double click or press f2 to start edit, I need user can directly edit once the cell has focus.

-In your example to end edit(or commit) user need to press enter or change focus by mouse, I need that once he press 0 or 1 it automatically commit and change focus.

Can it be done?

Can you provide Vb.net sample instead of c#?

Regards



SJ Sathiyathanam Jeyakumar Syncfusion Team May 15, 2023 02:29 PM UTC

Halcyon Security,

We are currently working on to achieve your requirements from our end. We will provide further details on May 17, 2023.




SB Sweatha Bharathi Syncfusion Team May 17, 2023 01:39 PM UTC

Halcyon Security,

We are still working on to achieve your requirements from our end. We will provide further details on May 19, 2023.




SJ Sathiyathanam Jeyakumar Syncfusion Team May 22, 2023 05:19 AM UTC

Halcyon Security,

We have prepared the VB sample and addressed all the requested concerns. Please review the sample and let us know if you have any further concerns.


Attachment: SfDataGridDemo_79c3c649.zip


HS Halcyon Security replied to Sathiyathanam Jeyakumar May 22, 2023 06:48 AM UTC

I tested the sample, it's work, but I found some concerns:

-sometime when focus is on the P5 column annd I press 0 or 1 it jump to the next row without change the cell value according with the button pressed.

-If I type fast it lose some input( it jump from a cell to another, but it not change the values: try to change all the table to 1 or to 0 pressing many time the same value you'll see that it miss some cells.

-I can't edit using numpad keys.

-user still able to digit numbers like 10 or 11 if he place the cursor before the number in the cell, it should not be able to do that.



SG Santhosh Govindasamy Syncfusion Team May 23, 2023 01:53 PM UTC

Halcyon Security,

We are still working on to achieve your requirements from our end. We will provide further details on May 25, 2023.



SB Sweatha Bharathi Syncfusion Team May 25, 2023 01:47 PM UTC


Halcyon Security,


Query

Comments

-sometime when focus is on the P5 column and I press 0 or 1 it jump to the next row without change the cell value according with the button pressed.

-If I type fast it lose some input( it jump from a cell to another, but it not change the values: try to change all the table to 1 or to 0 pressing many time the same value you'll see that it miss some cells.

 

 

Based on the provided information, we are unable to replicate the issue from our end. Kindly share the replicating issue as it will be helpful to proceed further.

-I can't edit using numpad keys.

-user still able to digit numbers like 10 or 11 if he place the cursor before the number in the cell, it should not be able to do that.

 

 

We have achieved your requirement. Please review the sample and let us know if you need any further assistance.



Attachment: SfDataGridDemo_fd23d34d.zip


HS Halcyon Security June 8, 2023 08:12 PM UTC

Could be done also in winform?



SJ Sathiyathanam Jeyakumar Syncfusion Team June 9, 2023 12:55 PM UTC

Halcyon Security,


Currently, we are assessing the feasibility of achieving the same requirement in WinForms. We will provide you with further details on June 13, 2023.



SB Sweatha Bharathi Syncfusion Team June 13, 2023 02:17 PM UTC

Halcyon Security,


Still, we are working of achieving the same requirement in WinForms. We will provide you with further details on June 15, 2023.



SB Sweatha Bharathi Syncfusion Team June 15, 2023 01:48 PM UTC


Halcyon Security,


We have prepared a Winforms sample based on your requirements. Please review the sample and let us know if any further assistance is required.


Attachment: WinformsSample_a3a971d1.zip


HS Halcyon Security replied to Sweatha Bharathi June 20, 2023 06:18 PM UTC

I found 1 iusse, in previus example (WPF) when user press 1 or 0 (one time) it jump to the next cell, in latest example it need to press 2 times.

Since I'm working in vb.net could you convert it please?



SB Sweatha Bharathi Syncfusion Team June 21, 2023 02:01 PM UTC

Halcyon Security,


We have prepared the VB sample and addressed your concerns. Please review the sample and let us know if you have any further concerns.


Attachment: WinformsVbSample_6e0e9250.zip

Loader.
Up arrow icon