Custom EditTrigger

11 posts, 0 answers
  1. Ludovic Gerbault
    Ludovic Gerbault avatar
    226 posts
    Member since:
    Apr 2009

    Posted 13 Sep 2009 Link to this post

    Hello

    I just saw that the last build of the radcontrols provides with an edittrigger property that allows to set the event that would make the grid go into edit mode.

    Can this property can bu customized to use for instance the Enter key instead of one of the given choices ?
  2. Milan
    Admin
    Milan avatar
    1989 posts

    Posted 14 Sep 2009 Link to this post

    Hello Subileau Pascal,

    Unfortunately the edit triggers are not customizable but  we could consider adding the option to enter edit mode when the enter key is pressed  if such option is required for your scenario.

    Kind regards,
    Milan
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  3. DevCraft banner
  4. Ludovic Gerbault
    Ludovic Gerbault avatar
    226 posts
    Member since:
    Apr 2009

    Posted 15 Sep 2009 Link to this post

    Actually, in my scenario, the ideal behaviour would be that the enter key would trigger a serie of events which would be the following :

    Validate the current cell in edit mode (CellEditEnded Event)
    Focus the next cell in the row
    Put this cell in Edit mode

    if the current cell is the last cell in the row and there isn't anymore row, then insert a new row and focus the first cell of the new row in edit mode
    if there is another row, focus this next row and put its first cell in edit mode.

    That would be my scenario.

    by the way, the itemsource of the datagrid I'm using is a custom lightweight datatable and my grid might sometimes include gridviewcomboboxcolumns.


  5. Milan
    Admin
    Milan avatar
    1989 posts

    Posted 16 Sep 2009 Link to this post

    Hello Subileau Pascal,

    EditTrigger only specifies what action triggers the beginning of the editing sequence - it does not affect in any way what happerns after the editing ends. Here is some code that implements the functionatily that you have requested:

    // subsribe to the CellEditEnded event  
    private void gridvView_CellEditEnded(object sender, GridViewCellEditEndedEventArgs e)  
    {  
        if (e.NewData == e.OldData)  
            return;  
     
        // validate here  
     
        var cellColumnIndex = this.gridvView.Columns.IndexOf(e.Cell.Column);  
     
        if (cellColumnIndex < this.gridvView.Columns.Count - 1)  
        {  
            this.BeginCellEdit(e.Cell.ParentRow, cellColumnIndex + 1);  
        }  
        else 
        {  
            var rowIndex = this.gridvView.Items.IndexOf(e.Cell.DataContext);  
            var nextItem = this.gridvView.Items.Cast<object>().Skip(rowIndex + 1).FirstOrDefault();  
     
            if (nextItem != null)  
                this.EditNextRow(nextItem);  
            else 
                this.CreateNewRowAndEdit();  
        }  
    }  
     
    private void BeginCellEdit(GridViewRowItem row, int cellIndex)  
    {  
        var cell = row.Cells[cellIndex] as GridViewCell;  
        cell.IsCurrent = true;  
        this.gridvView.BeginEdit();  
    }  
     
    private void BeginDelayedCellEdit(object rowDataItem, int cellIndex)  
    {  
        this.Dispatcher.BeginInvoke(  
     
            (Action)delegate 
            {  
                var container2 = this.gridvView.ItemsControl.ItemsGenerator.ContainerFromItem(rowDataItem) as GridViewRow;  
     
                if (container2 != null)  
                    this.BeginCellEdit(container2, cellIndex);  
            });  
    }  
     
    private void CreateNewRowAndEdit()  
    {  
        this.gridvView.BeginInsert();  
        var lastItem = this.gridvView.Items.Cast<object>().Last();  
        BeginDelayedCellEdit(lastItem, 0);  
    }  
     
    private void EditNextRow(object rowData)  
    {  
        var container = this.gridvView.ItemsControl.ItemsGenerator.ContainerFromItem(rowData) as GridViewRow;  
        this.gridvView.BringDataItemIntoView(rowData);  
     
        BeginDelayedCellEdit(rowData, 0);  

    Hope this helps.

    Regards,
    Milan
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  6. Ludovic Gerbault
    Ludovic Gerbault avatar
    226 posts
    Member since:
    Apr 2009

    Posted 16 Sep 2009 Link to this post

    I've tried to implement this piece of code you gave me, and it works as expected for the first time.

    But then, for some reason, when I change the value of the next cell, the event is fired twice, and the third cell does not receive the focus.

    After that, the event is always fired twice and it doesn't work anymore anywhere, even on the cell it previously worked on.
    The first two columns are gridviewcomboBoxColumns by the way.

    Any idea why ?
  7. Ludovic Gerbault
    Ludovic Gerbault avatar
    226 posts
    Member since:
    Apr 2009

    Posted 18 Sep 2009 Link to this post

    Can someone please give me a hand with that ?
  8. Milan
    Admin
    Milan avatar
    1989 posts

    Posted 22 Sep 2009 Link to this post

    Hi Subileau Pascal,

    I have tried to reproduce the problem but without any success. Could you open a support ticket and send us your project to that we can try to reproduce the problem?

    Kind regards,
    Milan
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  9. Ludovic Gerbault
    Ludovic Gerbault avatar
    226 posts
    Member since:
    Apr 2009

    Posted 22 Sep 2009 Link to this post

    Well, actually, Ross helped me already getting my scenario to work.

    I was the one firing the event twice, cause it was both in the button click event and the lost focus event.

    Now, everything works fine, I even managed to make the Enter Key behave as I need to, now the last thing I need is to be able to disable a cell when another one is modified, and reenable it if the value is removed.

    I'm gonna try a few things out, and I'll probably get back to you if I need help with that.

    (but if you know of a simple way to do such a thing, please let me know)

    Thanks anyway.
  10. Ludovic Gerbault
    Ludovic Gerbault avatar
    226 posts
    Member since:
    Apr 2009

    Posted 23 Sep 2009 Link to this post

    I knew I'd be getting back to you.

    Here's my problem, I have these two pieces of code related to what happen when I quit the cell edit mode

    var element = e.Cell.ParentRow; 
                    var cellIndex = element.Cells.IndexOf(e.Cell); 
                    if (e.Cell.Column.Header.ToString().Contains("Débit") && e.NewData.ToString() != "0"
                    { 
                        ((GridViewCell)element.Cells[cellIndex + 1]).IsEnabled = false
                    } 
                    if (e.Cell.Column.Header.ToString().Contains("Crédit") && e.NewData.ToString() != "0"
                    { 
                        ((GridViewCell)element.Cells[cellIndex - 1]).IsEnabled = false
                    } 

    if (e.Key == Key.Enter) 
                { 
                    e.Handled = true
                    FormGrille.RowEditEnded -=new EventHandler<GridViewRowEditEndedEventArgs>(FormGrille_RowEditEnded); 
                    var rowIndex = this.FormGrille.Items.IndexOf(FormGrille.CurrentCell.ParentRow); 
                    var element = (GridViewRow)this.FormGrille.ItemsControl.ItemsGenerator.ContainerFromItem(FormGrille.CurrentItem); 
                    var cellIndex = element.Cells.IndexOf(FormGrille.CurrentCell); 
     
     
                    if (cellIndex + 1 > element.Cells.Count - 1) 
                    { 
                        FormGrille.RowEditEnded += new EventHandler<GridViewRowEditEndedEventArgs>(FormGrille_RowEditEnded); 
                        this.btn_new.Focus(); 
                    } 
                    else 
                    { 
                        if (((GridViewCell)element.Cells[cellIndex + 1]).IsEnabled == true
                        { 
                            ((GridViewCell)element.Cells[cellIndex + 1]).IsCurrent = true
                            FormGrille.BeginEdit(); 
                        } 
                        else 
                        { 
                            FormGrille.RowEditEnded += new EventHandler<GridViewRowEditEndedEventArgs>(FormGrille_RowEditEnded); 
                            this.btn_new.Focus(); 
                        } 
                    } 
                } 

    What I'm trying to do is that when one changes the value of the cell in a particular column, the cell in the next column of the same row must prevent anyone to enter anything. (accounting thing)
    I have an Enter Key handler that allows to navigate in the row just by pressing enter, and the roweditended is only fired when the user reaches the last cell.

    The problem is that the Key handler is getting in the way of the celleditended event by being fired before.
    I need the cell to be disabled so when the key handler detects if the next cell is either the last one or disabled, it would jump to the new row button.
    But since the key handler is fired before, the cell is always enable, and my code puts the next cell in edit mode, even if this one is disabled, and the focus is passed to the button anyway.

    One last thing, even if the cell seems to actually be disabled, it reenables itself when I add a new row using this code :

    private void Button_Click(object sender, RoutedEventArgs e) 
            { 
                DataRow row = new DataRow(); 
                for (int i = 0; i < structure.Columns.Count; i++) 
                { 
                    if (structure.Columns[i].DataType == typeof(string)) 
                    { 
                        row.Add(structure.Columns[i].ColumnName, ""); 
                    } 
                    if (structure.Columns[i].DataType == typeof(decimal)) 
                    { 
                        row.Add(structure.Columns[i].ColumnName, Convert.ToDecimal(0)); 
                    } 
                } 
                structure.Rows.Add(row); 
                FormGrille.Rebind(); 
                FormGrille.Focus(); 
     
                FormGrille.Dispatcher.BeginInvoke(this.EditLastRow); 
            } 
     
            private void EditLastRow() 
            { 
                this.FormGrille.ItemsControl.BringDataItemIntoView(this.FormGrille.Items[this.FormGrille.Items.Count - 1]); 
                var element = (GridViewRow)this.FormGrille.ItemsControl.ItemsGenerator.GenerateItemAtIndex(this.FormGrille.Items.Count - 1); 
                ((GridViewCell)element.Cells[0]).IsInEditMode = true
            }  

    and I have no idea why.

    Anyway, do you have any idea about how to proceed, or at least a way to force the order of the fired events.








  11. Ludovic Gerbault
    Ludovic Gerbault avatar
    226 posts
    Member since:
    Apr 2009

    Posted 24 Sep 2009 Link to this post

    Up :)
  12. Milan
    Admin
    Milan avatar
    1989 posts

    Posted 28 Sep 2009 Link to this post

    Hi Subileau Pascal,

    If you execute the logic in the KeyDown event handler  through the Dispatcher the logic will be executed after CellEditEnded. For example:

    void Row_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)  
    {  
        if (e.Key == Key.Enter)  
        {  
            this.Dispatcher.BeginInvoke(new Action(this.DelayedAction));  
        }  
    }  
     
    private void DelayedAction()  
    {  
        FormGrille.RowEditEnded -= new EventHandler<GridViewRowEditEndedEventArgs>(FormGrille_RowEditEnded);  
        var rowIndex = this.FormGrille.Items.IndexOf(FormGrille.CurrentCell.ParentRow);  
        var element = (GridViewRow)this.FormGrille.ItemsControl.ItemsGenerator.ContainerFromItem(FormGrille.CurrentItem);  
        var cellIndex = element.Cells.IndexOf(FormGrille.CurrentCell);  
     
     
        if (cellIndex + 1 > element.Cells.Count - 1)  
        {  
            FormGrille.RowEditEnded += new EventHandler<GridViewRowEditEndedEventArgs>(FormGrille_RowEditEnded);  
            this.btn_new.Focus();  
        }  
        else 
        {  
            if (((GridViewCell)element.Cells[cellIndex + 1]).IsEnabled == true)  
            {  
                ((GridViewCell)element.Cells[cellIndex + 1]).IsCurrent = true;  
                FormGrille.BeginEdit();  
            }  
            else 
            {  
                FormGrille.RowEditEnded += new EventHandler<GridViewRowEditEndedEventArgs>(FormGrille_RowEditEnded);  
                this.btn_new.Focus();  
            }  
        }    

    The other problem is a little bit more difficult to tackle. Whever you insert new item all rows will be recreated and as a result all cells will have their default state - enabled. One possible solution is to create a collection that will store information about all disabled cells. Whenever a row is loaded perform a check agains this collection - if some cells of the corresponding row were disabled just disable them again.

    Greetings,
    Milan
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
Back to Top
DevCraft banner