在 WPF 中使用垂直滚动条时启用日期选择器列

Datepicker column enabling itself when playing with vertical scrollbar in WPF

我有一个奇怪的错误,我需要一些救援。 我在 WPF 中有一个包含多个类型的多个列的网格。 这些列中的一个或多个是我通过 FrameElementFactory 创建的 DatePickers :

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

我已经使用一种方法在我的一个变量的特定状态下禁用我的网格的 DatePickers:

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;
        }
    }
}

问题是,当我玩我的网格电梯时,日期选择器无缘无故地不断启用和禁用。 例子: 我所有的 DatePicker 都启用了,我正在玩我的垂直滚动条,没问题。

我所有的 DatePickers 都被禁用了,我正在玩我的垂直滚动条。 1 Datepicker会突然出现enable: DatePicker enabled 1

我一直在玩滚动条,另一个日期选择器将启用: DatePicker enabled 2

你知道会发生什么吗?

感谢您的帮助。

这是因为 DataGrid.EnableRowVirtualization 默认为 true。这启用了 UI 虚拟化,这意味着 UI 滚动到视图之外的元素可以被处理或重新使用。因此,有时当将项目滚动回视图时,将通过您的工厂创建一个新的 DatePicker,当然,调用 SetChangeLockState 时这个新的 DatePicker 将不存在,因此不会被禁用。

一个快速修复方法是将 DataGrid.EnableRowVirtualization 设置为 false,但如果您有很多行,这可能不会非常高效。更好的解决方案是绑定而不是设置 IsEnabled 属性,例如使用 RelativeSource 到 Window 上的 属性。

感谢 Ben,这是代码:

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
                    });