为啥覆盖 .GetHashCode 会清除 WinForms 中的这些数据绑定值?

     2023-02-22     227

关键词:

【中文标题】为啥覆盖 .GetHashCode 会清除 WinForms 中的这些数据绑定值?【英文标题】:Why would overwriting .GetHashCode clear these databound values in WinForms?为什么覆盖 .GetHashCode 会清除 WinForms 中的这些数据绑定值? 【发布时间】:2014-08-01 22:50:58 【问题描述】:

我们遇到了一个奇怪的错误,我们在调试时遇到了问题。

我们有一个使用 Microsoft CAB、DevExpress 组件和 .Net 3.5 的 MDI 工作区。

如果用户在工作区中打开两个窗口,每个窗口都包含绑定到两个单独数据模型的 UserControl,然后将它们都最小化,则要最小化的第一个窗口会在第二个最小化时清除其绑定字段。

数据模型的.Equals.GetHashCode 方法已被覆盖,因此这两个数据模型被视为相等。如果我们改变它,使它们是唯一的,我们就不会得到这种行为。

这是一些显示问题的示例伪代码

var a = new MyWindow();
a.DataModel = new SomeClass(123);
a.ShowInMdiWorkspace();

var b = new MyWindow();
b.DataModel = new SomeClass(123);
b.ShowInMdiWorksace();

a.Minimize();

// If SomeClass.GetHashCode() is overwritten to consider two objects  
// as equal based on the value passed in, then the data bindings for A
// get cleared on this call. If SomeClass.GetHashCode is unique, then 
// this problem does not happen.
b.Minimize();

这是第二个窗口最小化时的调用堆栈:

在上面的堆栈跟踪中的EndEditSession() 调用中,它正在调用EndEditSession 以使第二 窗口最小化,而当堆栈跟踪通过[External Code] 到OnChange我设置的断点,它正在触发 first 窗口中的 change 方法。

EndEditSession() 是我们自定义的东西,看起来像这样

protected void EndEditSession()

    IBindingValue bv = null;

    if (_bindingValues == null)
        return;

    if (_data != null)
    
        foreach (KeyValuePair<string, IBindingValue> kvp in _bindingValues)
        
            bv = kvp.Value;
            if (bv.IsBindable)
                ((PropertyManager)bv.Component.BindingContext[_data]).EndCurrentEdit();
        
    


_bindingValues 在 UserControl 初始化其数据绑定时填充。键字段是绑定控件的名称,值字段是自定义对象,其中存储控件本身、控件名称、绑定值和默认值。 bv.Component 返回设置绑定的控件,在我的测试中是自定义的 DevExpress LookupEdit

_data 包含UserControl 的数据模型,我可以验证它是否设置为第二个窗口的实例。

我最初的想法是BindingContext 是共享的,因此返回了错误的PropertyManager,但是我已经验证了两个表单和控件的.BindingContext 是分开的。

GetHashCode 方法被覆盖以使这两个对象被视为相等时,是否有可能将UserControl 的两个单独副本绑定到数据模型的两个单独实例时会混淆其绑定?

我不太熟悉 WinForms 绑定系统的内部工作原理,也不了解 CAB 的 MDI 工作区是如何管理的。

我的理论是,当第一个窗口最小化时,它正在卸载控件以节省内存,然后当第二个窗口最小化管理绑定的内部哈希表时,会错误地混淆并运行更新以从第一个最小化窗口(现在为空白)并更新其数据源。这个理论有很多漏洞,但这是我唯一能想到的。

【问题讨论】:

【参考方案1】:

我不知道 WinForm 小部件的内部工作原理,但似乎既然您遇到了 overriding equals 的问题,那么您最好解决强>。

如果您需要为自己的目的评估平等:

一种方法是提供您自己的方法来评估相等性,而不是更改默认行为。

如果您的意图是更改小部件处理对象的方式:

一种方法是为您的类创建一个静态对象工厂。工厂可以维护使用弱引用创建的所有对象的集合。弱引用允许 GC 收集对象。然后工厂可以检查以前创建的对象的集合。如果找到匹配项,则返回现有匹配项。如果没有,则创建它。这样,您将拥有一个具有两个相等引用(相同内存)的单个对象,而不是让两个不同的对象评估两个相等(覆盖等于)。

希望这些其他方法之一可以解决您的问题。

【讨论】:

【参考方案2】:

BindingContext 对象不与任何其他 BindingContext 共享其字段和属性,因为它的字段和属性不是静态的。 但是,可以有一个BindingContext 对象用于多个控件。

在第一种情况下,如果多个控件具有相同的父级并且没有自己的BindingContext,则此控件的BindingContext 属性将返回Control.Parent(.Parent...).BindingContext 对象。 在第二种情况下,可能是这样的:

var bindingContext = new BindingContext();
var a = new SomeControl();
var b = new SomeControl();
a.BindingContext = bindingContext;
b.BindingContext = bindingContext;

在第三种情况下,BindingContext 可以用这种方式覆盖。 我不知道你的情况是怎么回事,所以我只能建议在初始化数据绑定之前做这样的事情:

var a = new SomeControl();
var b = new SomeControl();
a.BindingContext = new BindingContext();
b.BindingContext = new BindingContext();

如果这不能解决您的问题,那么您需要检查 _bindingValues 对象的填充情况。可能在填充此对象期间填充了错误的值。

【讨论】:

这也是我的第一个想法,但是在分配每个控件时仍然会出现同样的问题BindingContext @Rachel 你能提供一个示例项目吗?似乎没有足够的信息来说明您的问题。我认为问题不在于BindingContext。问题可能出在您的 _bindingValues 对象中。 我实际上无法在示例项目中重现这一点,我认为这是因为我没有在示例中使用智能部件创建完整的 MDI 工作区。我使用的示例代码只是一个带有 TabControl、一个自定义对象和一个带有自定义绑定代码的自定义 UserControl 的表单。我今天再试一次,看看能否在更大的示例项目中重现该问题。

为啥我需要覆盖 C# 中的 .Equals 和 GetHashCode [重复]

】为啥我需要覆盖C#中的.Equals和GetHashCode[重复]【英文标题】:WhydoIneedtooverridethe.EqualsandGetHashCodeinC#[duplicate]为什么我需要覆盖C#中的.Equals和GetHashCode[重复]【发布时间】:2013-08-1104:36:31【问题描述】:我正在使用EntityFramework5。在... 查看详情

如果在覆盖 Equals() 时未能覆盖 GetHashCode(),会出现啥问题? [复制]

】如果在覆盖Equals()时未能覆盖GetHashCode(),会出现啥问题?[复制]【英文标题】:WhatcangowrongifonefailstooverrideGetHashCode()whenoverridingEquals()?[duplicate]如果在覆盖Equals()时未能覆盖GetHashCode(),会出现什么问题?[复制]【发布时间】:2009-... 查看详情

覆盖 GetHashCode [重复]

】覆盖GetHashCode[重复]【英文标题】:OverridingGetHashCode[duplicate]【发布时间】:2011-05-1312:46:30【问题描述】:如您所知,GetHashCode返回一个半唯一值,可用于标识集合中的对象实例。作为一种好的做法,建议重写此方法并实现您自... 查看详情

未调用 C#GetHashCode/Equals 覆盖

】未调用C#GetHashCode/Equals覆盖【英文标题】:C#GetHashCode/Equalsoverridenotcalled【发布时间】:2010-11-0622:42:14【问题描述】:我遇到了GetHashCode和Equals的问题,我已经为一个类覆盖了这些问题。我正在使用运算符==来验证两者是否相等... 查看详情

如何在没有任何数字作为字段的情况下覆盖 GetHashCode()?

】如何在没有任何数字作为字段的情况下覆盖GetHashCode()?【英文标题】:HowdoIoverrideGetHashCode()withoutanynumbersasfields?【发布时间】:2017-02-0114:05:17【问题描述】:所有显示如何覆盖Equals(object)和GetHashCode()的资源都使用数字字段来实... 查看详情

包含通用数组的对象的 GetHashCode 覆盖

】包含通用数组的对象的GetHashCode覆盖【英文标题】:GetHashCodeoverrideofobjectcontaininggenericarray【发布时间】:2009-03-1214:08:06【问题描述】:我有一个包含以下两个属性的类:publicintIdget;privateset;publicT[]Valuesget;privateset;我已经做到了I... 查看详情

为啥 GetHashCode 很重要,我们可以在哪里使用它? [复制]

】为啥GetHashCode很重要,我们可以在哪里使用它?[复制]【英文标题】:WhyisGetHashCodeimportantandwherecanweuseit?[duplicate]为什么GetHashCode很重要,我们可以在哪里使用它?[复制]【发布时间】:2011-05-0510:03:30【问题描述】:可能重复:Why... 查看详情

为啥我们需要在对象模型项目中使用 GetHashCode() 函数? [复制]

】为啥我们需要在对象模型项目中使用GetHashCode()函数?[复制]【英文标题】:WhydoweneedGetHashCode()functionintheObjectModelProject?[duplicate]为什么我们需要在对象模型项目中使用GetHashCode()函数?[复制]【发布时间】:2012-06-2116:07:59【问题... 查看详情

正确实施 GetHashCode [重复]

】正确实施GetHashCode[重复]【英文标题】:ImplementingGetHashCodecorrectly[duplicate]【发布时间】:2012-02-1901:16:24【问题描述】:我想听听社区的意见,我应该如何为我的对象实现GetHashCode(或覆盖它)。我知道如果我覆盖equals方法,我... 查看详情

如何在Castle.Core中实现IProxyGenerationHook的类中实现Equals和GetHashCode的覆盖方法?

...如何在Castle.Core中实现IProxyGenerationHook的类中实现Equals和GetHashCode的覆盖方法?【英文标题】:HowtoimplementtheoverridemethodsofEqualsandGetHashCodeinaclassthatimplementsIProxyGenerationHookinCastle.Core?【发布时间】:2021-04-1817:06:39【问题描述】:阅读t... 查看详情

为啥清除列表会清除第一个? [复制]

】为啥清除列表会清除第一个?[复制]【英文标题】:Whydoesclearingalistclearthefirst?[duplicate]为什么清除列表会清除第一个?[复制]【发布时间】:2021-12-0911:38:16【问题描述】:我编写了这个小例子,以便您了解我的问题。我制作了... 查看详情

gitmerge为啥会覆盖

参考技术A覆盖啥。merge就是合并,在没冲突的时候,会自动merge。有啥问题。本回答被提问者和网友采纳 查看详情

为啥覆盖会更改列名

】为啥覆盖会更改列名【英文标题】:Whydoesoverridingchangecolumnnames为什么覆盖会更改列名【发布时间】:2012-09-2601:15:44【问题描述】:我使用的是rev监听器的默认实现,正如预期的那样,我的REVINFO表中的列是:revtstmp和rev。但是... 查看详情

为啥 UIButton 会覆盖 UITapGestureRecognizer?

】为啥UIButton会覆盖UITapGestureRecognizer?【英文标题】:WhyisaUIButtonisoverridingUITapGestureRecognizer?为什么UIButton会覆盖UITapGestureRecognizer?【发布时间】:2010-09-3023:41:49【问题描述】:我有一个带有2个子视图的父UIView:一个UIButton和一... 查看详情

自定义类型 GetHashCode [重复]

】自定义类型GetHashCode[重复]【英文标题】:CustomtypeGetHashCode[duplicate]【发布时间】:2011-06-3021:46:17【问题描述】:可能重复:WhatisthebestalgorithmforanoverriddenSystem.Object.GetHashCode?我需要为由三个字符串组成的类型覆盖GetHashCode方法。... 查看详情

为啥清除 Derived Data 会清除 Xcode 中的各种错误?

】为啥清除DerivedData会清除Xcode中的各种错误?【英文标题】:WhydoesclearingDerivedDataclearupvariouserrorsinXcode?为什么清除DerivedData会清除Xcode中的各种错误?【发布时间】:2016-12-1620:15:01【问题描述】:通常,人们在xcode中遇到各种问... 查看详情

linux清除ssh重新生成会覆盖原有的嘛

参考技术A会。在linux系统中清除ssh文件后,如果需要恢复该文件的使用,可以对其进行重新生成,并且该文件会覆盖掉之前原有的旧文件。 查看详情

覆盖 isHighlighted 仍然会改变 UIControlState - 为啥?

】覆盖isHighlighted仍然会改变UIControlState-为啥?【英文标题】:OverridingisHighlightedstillchangesUIControlState-why?覆盖isHighlighted仍然会改变UIControlState-为什么?【发布时间】:2018-08-1318:09:16【问题描述】:在一个UIControl中,如果我重写isHi... 查看详情