1

我不确定我这样做是否正确。我在列表框中有一个对象列表,需要使用 IndexOf 来获取列表中对象的索引。

if AlarmListBox.items.indexOf(alrm.Tagname) = -1 then

alrm 是 TAlarm 类的对象。

基于 StackOverflow C# 问题(How Can I Get the Index of An Item in a ListBox?),我尝试覆盖 GetHashCode 和 Equals 方法,但它仍然无法正常工作。

重写方法:

TAlarm = class(System.Object)
  TagName:string;
  private
  protected
  public
  method Equals(obj:System.Object):Boolean; override;
  method GetHashCode:Int32; Override;
end;

method TAlarm.Equals(obj: system.Object):Boolean;
begin
    result := TAlarm(obj).Tagname.Equals(self.Tagname);
end;

method TAlarm.GetHashCode:Int32;
begin
    result := self.GetHashCode;
end;

这就是我填充 AlarmListBox 的方式:

AlmGrp:= new TAlarmGroup;
AlarmListBox.items.Add(AlmGrp);

编译器编译没有任何错误,但是当我逐行调试程序时,它总是返回 -1 并且这些被覆盖的方法永远不会被调用或触发。

我是否正确实施了这些覆盖?如果没有,我应该如何覆盖它们?

示例代码或提示或线索将不胜感激。谢谢,

更新:对于大卫赫弗南和其他评论或回答的人,我认为问题可能是我传递了两个不同的对象,正如 Rob 的最后评论所述。我确实使用 TAlarmGroup 填充列表框(UI),但将 TAlarm 传递到 IndexOf,尽管它们都是相同的类。这可能是我的问题。我真正想做的是用 TAlarmGroup 对象填充列表框,并通过 listbox.indexof 通过传入字符串(标记名)来搜索对象位置。这就是它在 Delphi XE 上的工作方式,效果很好。上面的代码不是实际的代码。一旦我清理了代码中的混乱,它可能会在不覆盖 GetHashcode 和 Equals 方法的情况下工作。

更新:我想,我在这里偶然发现了一些东西。在 Delphi XE 或更低版本中,ListBox (UI) 提供了一个名为 AddObject 的方法。它的参数分别是一个字符串和一个对象。因此,当我将对象填充到列表框中时,我还提供了与之配套的字符串。当我搜索时,我传入了一个字符串或警报组名称。IndexOf 针对我提供的每个对象的字符串而不是对象的字段 (TagName) 搜索此字符串。在 Delphi Prism 中,listbox 没有与 AddObject 方法类似的方法,但只有 Add 只接受对象作为参数。

4

1 回答 1

2

TAlarm这是一个使用您提供的基类做您想做的事情的示例。我还提供了重载的实现,EqualsGetHashCode似乎有效。(同样,我不是 Prism/.NET 开发人员;只是想在这里提供帮助。)

// In AlarmClass.pas
type
  TAlarm = class(System.Object)
    TagName:string;
  private
  protected
  public
    constructor;
    method Equals(obj:System.Object): Boolean; override;
    method GetHashCode:Int32; Override;
    method ToString(): String; override;
end;

implementation

method TAlarm.GetHashCode: Int32;
begin
  if Self = nil then
    Result := inherited 
  else
    Result := Self.TagName.GetHashCode;
end;

constructor TAlarm;
begin
  inherited;
end;

method TAlarm.Equals(obj: System.Object): Boolean;
begin
  if  (obj = nil) or (GetType() <> obj.GetType()) then
    Exit(False);
  Result := TAlarm(obj).TagName.Equals(Self.TagName);
end;

method TAlarm.ToString(): String;
begin
  Result := Self.TagName;
end;

// In MainForm.pas
method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
var
  Idx: Integer;
begin
  Idx := ComboBox1.SelectedIndex;
  if Idx <> -1 then
    ListBox1.SelectedIndex := ListBox1.Items.IndexOf(ComboBox1.Items[Idx]);
end;

method MainForm.MainForm_Load(sender: System.Object; e: System.EventArgs);
var
  i, j: Integer;
  Alarm: TAlarm;
  aList: Array[0..4] of Object;
  aFind: Array[0..1] of Object;
begin
  j := 0;
  for i := 0 to 4 do
  begin
    Alarm := new TAlarm;
    Alarm.TagName := String.Format('Alarm{0}', i);
    aList[i] := Alarm;
    // Place items 1 & 3 in another array of searchable items -
    // just for fun. Not suggesting implementing your app this way
    // by any means.
    if (i mod 2) > 0 then
    begin
      aFind[j] := Alarm;
      Inc(j);
    end;
  end;
  ListBox1.Items.AddRange(aList);
  ComboBox1.Items.AddRange(aFind);
end;

ComboBox以下是单击 后在中选择的项目时的外观Button

在 ListBox 中找到的对象的屏幕截图

于 2011-09-15T23:24:36.697 回答