【问题标题】:C# WPF Datagrid with recycling virtualization具有回收虚拟化的 C# WPF Datagrid
【发布时间】:2016-06-22 01:54:45
【问题描述】:

我基于 wpf 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
}

`

【问题讨论】:

    标签: c# wpf datagrid virtualization recycle


    【解决方案1】:

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

    VirtualizingStackPanel.VirtualizationMode="Standard"
    

    这里发生的是默认值(回收)重用容器,并且在某些情况下绑定无法更新 UI。选择标准虚拟化模式强制重新生成单元。 (它有性能影响)。

    查看此链接了解更多详情:VirtualizationMode

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-08-02
      • 2010-12-01
      • 1970-01-01
      • 2017-11-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多