具有循环虚拟化功能的C#WPF Datagrid

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了具有循环虚拟化功能的C#WPF Datagrid相关的知识,希望对你有一定的参考价值。

我基于wpf datagrid制作了datagrid。我使用回收虚拟化,并在滚动后以随机顺序显示了一些单元。当我完全更改一个单元格时,但是当我滚动到datagrid的末尾时,返回并尝试更改一个单元格,则另一个单元格也会更改。下面的代码示例

您能帮我解决这个问题吗?

单元格模板的集合:

                <gridColumns:CTemplateContainer
                        CellTemplate="{StaticResource GenericCellTemplate}"
                        CellEditingTemplate="{StaticResource GenericCellTemplate}"/>
                <gridColumns:CTemplateContainer
                        Key="Comment"
                        CellTemplate="{StaticResource GenericCellTemplate}"
                        CellEditingTemplate="{StaticResource CellEditTemplate}"/>
                <gridColumns:CTemplateContainer
                        Key="Checked"
                        CellTemplate="{StaticResource GenericCellCheckedTemplate}"
                        CellEditingTemplate="{StaticResource GenericCellCheckedTemplate}"/>

            </gridColumns:ContainerCollection>

        </grid:DataGridExtended.TemplateContainers>

模板:

                <TextBlock Text="{Binding Path=Value, Mode=TwoWay}" >
                    <TextBlock.Resources>
                        <Style TargetType="TextBlock" BasedOn="{StaticResource stlTextDefaultBinding}">
                        </Style>
                    </TextBlock.Resources>
                </TextBlock>
            </Border>
        </DataTemplate>

        <DataTemplate x:Key="CellEditTemplate">
            <TextBox Focusable="True" FocusManager.FocusedElement="{Binding RelativeSource={RelativeSource Self}}"
                    DataContext="{TemplateBinding DataContext}"
                    Text="{Binding Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged,
                    ValidatesOnDataErrors=True,
                    NotifyOnValidationError=True}"
                    Tag="{TemplateBinding Tag}" BorderThickness="0" Padding="0">
            </TextBox>
        </DataTemplate>

列代码

`class CDataGridTemplateColumn:ctrWPF.DataGridTemplateColumn{私人绑定ItemContentBinding;

    public CDataGridTemplateColumn(object header, string path, CTemplateContainer container)
    {
        Header = header;

        var binding = new Binding();
        binding.Path = new PropertyPath("Cells[" + path + "]");

        Binding = binding;

        FillTemplates(container);
    }

    public CDataGridTemplateColumn(ctrWPF.DataGridColumn col, string path, CTemplateContainer container)
    {
        try
        {
            var binding = new Binding() { Mode = BindingMode.TwoWay };
            binding.Path = new PropertyPath(path);
            Binding = binding;

            FillTemplates(container);

            CGridColumnHelper.InitBaseColumn(this, col);
        }
        catch (Exception ex)
        { }
    }

    private void FillTemplates(CTemplateContainer container)
    {
        CellTemplate = container.CellTemplate;
        CellEditingTemplate = container.CellEditingTemplate;
        CellEditingTemplateSelector = container.TemplateSelector;

        if (container.CellStyle == null)
            return;

        CellStyle = container.CellStyle;
    }

    public void InitBinding()
    {
        if (BindingColumn == null)
            throw new ArgumentNullException("BindingColumn null");

        ItemContentBinding = new ctrWPFData.Binding("Cells[" + BindingColumn.Index + "].Value");
    }

    #region Binding

    private BindingBase _binding;

    protected virtual void OnBindingChanged(BindingBase oldBinding, BindingBase newBinding)
    {
        base.NotifyPropertyChanged("Binding");
    }

    public virtual BindingBase Binding
    {
        get
        {
            return this._binding;
        }
        set
        {
            if (this._binding != value)
            {
                BindingBase oldBinding = this._binding;
                this._binding = value;
                base.SortMemberPath = ((Binding)value).Path.Path + ".Value";
                this.ClipboardContentBinding = new Binding(((Binding)value).Path.Path + ".Value");
                base.CoerceValue(DataGridColumn.SortMemberPathProperty);
                this.OnBindingChanged(oldBinding, this._binding);
            }
        }
    }

    private void InitValidation(BindingBase binding)
    {
        Binding _bind = binding as Binding;

        if (_bind == null)
            return;

        _bind.NotifyOnValidationError = true;
        _bind.ValidatesOnDataErrors = true;
        _bind.ValidatesOnNotifyDataErrors = true;
    }

    public override BindingBase ClipboardContentBinding
    {
        get
        {
            return (base.ClipboardContentBinding ?? this.Binding);
        }
        set
        {
            base.ClipboardContentBinding = value;
        }
    }

    private DataTemplate ChooseCellTemplate(bool isEditing)
    {
        DataTemplate template = null;
        if (isEditing)
        {
            template = this.CellEditingTemplate;
        }
        if (template == null)
        {
            template = this.CellTemplate;
        }
        return template;
    }

    private DataTemplateSelector ChooseCellTemplateSelector(bool isEditing)
    {
        DataTemplateSelector templateSelector = null;
        if (isEditing)
        {
            templateSelector = this.CellEditingTemplateSelector;
        }
        if (templateSelector == null)
        {
            templateSelector = this.CellTemplateSelector;
        }
        return templateSelector;
    }

    protected override FrameworkElement GenerateEditingElement(System.Windows.Controls.DataGridCell cell, object dataItem)
    {
        return this.LoadTemplateContent(true, dataItem, cell);
    }

    protected override FrameworkElement GenerateElement(System.Windows.Controls.DataGridCell cell, object dataItem)
    {
        return this.LoadTemplateContent(false, dataItem, cell);
    }

    private void ApplyBinding(DependencyObject target, DependencyProperty property)
    {
        BindingBase binding = this.Binding;
        if (binding != null)
        {
            BindingOperations.SetBinding(target, property, binding);
        }
        else
        {
            BindingOperations.SetBinding(target, property, new Binding());
        }
    }

    private FrameworkElement LoadTemplateContent(bool isEditing, object dataItem, System.Windows.Controls.DataGridCell cell)
    {
        DataTemplate template = this.ChooseCellTemplate(isEditing);
        DataTemplateSelector templateSelector = this.ChooseCellTemplateSelector(isEditing);

        if ((template == null) && (templateSelector == null))
        {
            return null;
        }


        ContentPresenter contentPresenter = new ContentPresenter();

        this.ApplyBinding(contentPresenter, ContentPresenter.ContentProperty);

        contentPresenter.ContentTemplate = template;
        contentPresenter.ContentTemplateSelector = templateSelector;
        contentPresenter.Name = "TEST";
        return contentPresenter;
    }

    #endregion
}

`

答案

我知道这个线程已经很老了,您现在可能已经找到了答案,但是它可以帮助其他人。创建自定义可过滤数据网格并更改虚拟化模式(在xaml中,在datagrid属性中)时,我遇到了同样的问题。

VirtualizingStackPanel.VirtualizationMode="Standard"

这里发生的事情是默认值(回收)会重新使用容器,在某些情况下,绑定无法更新UI。进入标准虚拟化模式将强制重新生成单元。 (它会对性能产生影响)。

请参阅此链接以获取更多详细信息:VirtualizationMode

以上是关于具有循环虚拟化功能的C#WPF Datagrid的主要内容,如果未能解决你的问题,请参考以下文章

WPF:关于ScrollViewer中嵌套Datagrid的问题

WPF Datagrid contains ComboBox while display textblock when display and combobox in editing mode(示例代

WPF DataGrid Multiselect启用了虚拟化MVVM

设置datagrid行背景颜色WPF - 循环[关闭]

带有分组的 WPF DataGrid 虚拟化

WPF ListBox/ListView/DataGrid 列表滚动与虚拟化