Make specific dynamic column not unfreezable

1 Answer 125 Views
GridView
Eldoir
Top achievements
Rank 2
Iron
Iron
Iron
Eldoir asked on 02 Nov 2022, 05:19 PM | edited on 03 Nov 2022, 11:26 AM

Hello, actually I think I should have named this topic: "How to prevent drag'n'drop on a specific column", because it has little to do with the freeze, and most likely nothing to do with the fact that it's generated dynamically.

What I want is to display a specific column, and keep it in the view at anytime. The user must not be able to move it.

To this end, I set the LeftFrozenColumnCount to 1, and I move this column to index 0 when I'm done generating my columns, to ensure it's the one that is frozen. This is the initial setup when the user comes in.

Now, I want my user to be able to freeze and unfreeze any columns they want; I just need this specific column to NOT be unfreezable, so that it always stays in view.

I tried to set IsReorderable to false on this specific column, but then I can no longer freeze columns to the left of this column, and I want users to be able to do this.

I stumbled upon this thread: https://www.telerik.com/forums/preventing-resizing-and-re-ordering-of-specific-columns#850549

What Gary describes is exactly the behavior I'm looking for:

 Looking at the WPFToolkit grid, setting "CanUserReorder" to false means the user cannot drag and drop the column.  But after doing some testing, you're right in that a user can still just drop other columns in front to change it's posistion.

For now, I subscribe to the PreviewDrop event of the RadGridView, and I cancel the drop by setting e.Handled to true when the dropped data is the GridViewHeaderCell of this specific column. It works, but I want to prevent the drag in the first place, not just prevent the drop. Applying this technique to PreviewDragEnter, or DragEnter, does not seem to have any effect. 

How can I achieve this? Thanks!

1 Answer, 1 is accepted

Sort by
0
Dilyan Traykov
Telerik team
answered on 07 Nov 2022, 01:51 PM

Hello Eldoir,

To disable the drag and drop of this particular column, you can set the attached DragDropManager.AllowDrag and DragDropManager.AllowCapturedDrag properties to False:

        private void GridView_CellLoaded(object sender, Telerik.Windows.Controls.GridView.CellEventArgs e)
        {
            if (e.Cell is GridViewHeaderCell && e.Cell.DataColumn.DataMemberBinding.Path.Path == "Name")
            {
                Dispatcher.BeginInvoke(new Action(() =>
                {
                    DragDropManager.SetAllowDrag(e.Cell, false);
                    DragDropManager.SetAllowCapturedDrag(e.Cell, false);
                }), System.Windows.Threading.DispatcherPriority.Loaded);
            }
        }

You can notice that as these properties are internally set to true once the cell is loaded I've delayed this action by utilizing the Dispatcher.

Please note that this will also allow columns to be dragged to the left of this column unless its IsReorderable property is set to False. In that case, users can drag the frozen columns splitter and exclude the column. To prevent this, you can handle the FrozenColumnsChanged event like so:

        private void GridView_FrozenColumnsChanged(object sender, Telerik.Windows.Controls.GridView.GridView.FrozenColumnsChangedEventArgs e)
        {
            var mandatoryColumn = e.RemovedFrozenColumns.FirstOrDefault(c => c.Header.ToString() == "Name");
            if (mandatoryColumn != null)
            {
                this.playersGrid.LeftFrozenColumnCount = mandatoryColumn.DisplayIndex + 1;
            }
        }

To demonstrate both these approaches in action, I've prepared a small sample project. Please have a look and let me know if something similar would also be applicable in your original application.

Regards,
Dilyan Traykov
Progress Telerik

Love the Telerik and Kendo UI products and believe more people should try them? Invite a fellow developer to become a Progress customer and each of you can get a $50 Amazon gift voucher.

Eldoir
Top achievements
Rank 2
Iron
Iron
Iron
commented on 07 Nov 2022, 02:01 PM | edited

Hello Dilyan, thanks for your answer. It's an interesting solution.
I've actually come with another one, that I've found a few days after posting this thread and forgot to tell about it!
What I did was attach a behavior to my RadGridView with this code:

internal sealed class DragDropBehavior : Behavior<RadGridView>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        DragDropManager.AddDragInitializeHandler(AssociatedObject, OnDragInitialize, true);
    }

    protected override void OnDetaching()
    {
        DragDropManager.RemoveDragInitializeHandler(AssociatedObject, OnDragInitialize);
        base.OnDetaching();
    }

    private void OnDragInitialize(object sender, DragInitializeEventArgs args)
    {
        if (args.Data is IDataObject dataObject
            && dataObject.GetData("DraggedCell") is GridViewHeaderCell cell
            && cell.DataColumn is AttributeGridViewDataColumn column
            && !column.IsDraggable)
        {
            args.Cancel = true;
        }
    }
}

A few things to note with this approach:

  • In OnDragInitialize, I rely on whether the column has IsDraggable to true. This is because AttributeGridViewDataColumn is my own class of column, inheriting from GridViewDataColumn. When generating my columns, I set this IsDraggable property.
  • GetData("DraggedCell") comes from my own trial-and-error when playing with System.Windows.IDataObject interface. I guess this is not a very resilient piece of code, since the name of this property can change through updates on your side. But that's something I'm up to, since we don't do these updates that often.
Dilyan Traykov
Telerik team
commented on 08 Nov 2022, 01:56 PM

Hello Eldoir,

Thank you for sharing your solution.

This is indeed an interesting approach and if it works for you, you're free to use it. Indeed, it is dependent on the DraggedCell object but it is unlikely that we will change this name in the future.

Nonetheless, should you come across any issues, feel free to also give the approach I suggested earlier a try.

Tags
GridView
Asked by
Eldoir
Top achievements
Rank 2
Iron
Iron
Iron
Answers by
Dilyan Traykov
Telerik team
Share this question
or