Datepicker column enabling itself when playing with vertical scrollbar in WPF

203 views Asked by At

I have a weird bug and i need some rescue. I have a grid with several column of multiple types in WPF. One or several of these columns are DatePickers that I created through a FrameElementFactory :

FrameworkElementFactory dateFactory = new FrameworkElementFactory(typeof(DatePicker));
...
column = new DataGridTemplateColumn { CellTemplate = new DataTemplate
{ VisualTree = dateFactory } };
this._mainDatagrid.Columns.Add(column);

I have put a method to disable the DatePickers of my grid on a certain state of one of my variable:

private IEnumerable<DataGridRow> GetDataGridRows(DataGrid grid)
{
    //return the Datagrid Rows
}

public void SetChangeLockState(bool isUnlocked)
{
    IEnumerable<DataGridRow> _rows = this.GetDataGridRows(this._mainDatagrid);
    foreach (DataGridColumn _column in this._mainDatagrid.Columns)
    {
        if (_column.GetType() != typeof(DataGridTemplateColumn)) continue;
        foreach (DataGridRow _row in _rows)
        {
            FrameworkElement frameworkElement = _column.GetCellContent(_row);
            if (frameworkElement != null) frameworkElement.IsEnabled = !isUnlocked;
        }
    }
}

The problem is that when I am playing with the elevator of my grid, the Datepicker keep enabling and disabling for no reason. Example: All my DatePicker are enabled, I am playing with my vertical scroll bar, no problem.

All my DatePickers are Disabled, I am playing with my vertical scroll bar. 1 Datepicker will suddenly appear enable : DatePicker enabled 1

I am keeping playing with the scrollbar and another Datepicker will go enabled : DatePicker enabled 2

Have you any idea of what could happen ?

Thanks for your help.

2

There are 2 answers

1
Ben Jackson On BEST ANSWER

This will be because DataGrid.EnableRowVirtualization defaults to true. This enables UI virtualisation, which means that UI Elements that are scrolled out of view may be disposed or reused. Thus on occasions when scrolling an item back into view a new DatePicker will be created via your factory, and of course this new DatePicker will not have existed when SetChangeLockState was called and thus will not be disabled.

A quick fix would be to set DataGrid.EnableRowVirtualization to false, but this may not be very performant if you have lots of rows. A better solution would be to bind rather than set the IsEnabled property, e.g. to a property on your Window using RelativeSource.

0
goatman On

Thanks to Ben, here is the code :

dateFactory.SetBinding(
                    //My IsEnabled property I wanted to change
                    IsEnabledProperty,
                    new Binding("IsLockedDatagrid")
                    {
                        //Datagridwidget is the datagrid I am using where I can found the IsLockedDatagrid boolean variable (in my xaml)
                        RelativeSource =
                            new RelativeSource(RelativeSourceMode.FindAncestor, typeof(DataGridWidget), 1),
                        Mode = BindingMode.OneWay,
                        UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged
                    });