继承ListBox.ObjectCollection类 [英] Inheriting a ListBox.ObjectCollection Class

查看:86
本文介绍了继承ListBox.ObjectCollection类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,



我正在尝试创建ListBox控件的扩展版本。我希望能够为Items集合添加其他方法。考虑我的代码:



Hello,

I am trying to create an extended version of the ListBox Control. I want to be able to add additional methods to the Items collection. Consider my code:

public class ListBoxEx : ListBox
{
	private ObjectCollectionEx itm = null;

	public ListBoxEx()
	{
		itm = new ObjectCollectionEx(this);
	}
	~ListBoxEx()
	{
		itm.Clear();
		itm = null;
	}
	new public ObjectCollectionEx Items
	{
		get
		{
			return this.itm;
		}
		set
		{
			this.itm = value;
		}
	}
}

public class ObjectCollectionEx : ListBox.ObjectCollection
{
	private ListBoxEx listBox = null;

	public ObjectCollectionEx(ListBoxEx owner) : base((ListBox)owner)
	{
		this.listBox = owner;
	}

	public ObjectCollectionEx(ListBoxEx owner, ObjectCollectionEx value) : base((ListBox)owner, (ListBox.ObjectCollection)value)
	{
		this.listBox = owner;
	}

	public ObjectCollectionEx(ListBoxEx owner, object[] value) : base((ListBox)owner, value)
	{
		this.listBox = owner;
	}

	public new int Add(object item)
	{
		return base.Add(item);
	}

	public new void AddRange(ListBox.ObjectCollection value)
	{
		base.AddRange(value);
	}

	public new void AddRange(object[] items)
	{
		base.AddRange(items);
	}

	public new void Clear()
	{
		base.Clear();
	}

	public new bool Contains(object value)
	{
		return base.Contains(value);
	}

	public new void CopyTo(object[] destination, int arrayIndex)
	{
		base.CopyTo(destination, arrayIndex);
	}

	public new int Count
	{
		get
		{
			return base.Count;
		}
	}

	public new bool Equals(object obj)
	{
		return base.Equals(obj);
	}

	public new int IndexOf(object value)
	{
		return base.IndexOf(value);
	}

	public new void Insert(int index, object item)
	{
		base.Insert(index, item);
	}

	public new void Remove(object value)
	{
		base.Remove(value);
	}

	public new void RemoveAt(int index)
	{
		base.RemoveAt(index);
	}
	
	public void NewMethod()
	{
		//do something
	}
}





当我使用新的ListBox时,一切都很好,除非我尝试这样做:





When I use the new ListBox, all is well, except when I try to do something like this:

        private void button1_Click(object sender, EventArgs e)
{
// not actual code, for example purposes only.
    listBoxEx1.Items.Add("Hello");
    listBoxEx1.Items.Add("World");
    MessageBox.Show(listBoxEx1.SelectedIndex);    // returns -1, unless I have selected an item previously... [problem #1 — SA] normal behaviour
    listBoxEx1.SelectedIndex = 0;                 // throws an InvalidArgument exception (Value of '0' is not valid for 'SelectedIndex'.) [problem #2 — SA]
    MessageBox.Show(listBoxEx1.SelectedItem);     // throws an IndexOutOfRange Exception if an item is selected, otherwise NullReferenceException is thrown. [problem #3 — SA]
}





我真的在这里结束了,所以请如果有人可以请求帮助,我会永远感激不尽。谢谢。



I'm really at wit's end here, so please, if anybody could please help, I'd be eternally grateful. Thanks.

推荐答案

请查看您的代码示例:我将它们编号为#1 ..#3。



问题#1

不是问题;这是正确的行为。



问题#2和#3

这是因为通过添加 new public ObjectCollectionEx Items 隐藏 Items 属性。从这一刻起,您有两个项目集合。如果您使用,例如,继承添加,则会向继承的更正添加一些项目。但是当您尝试使用 Items 属性访问该项时,您将访问新的集合,并且无法访问继承的集合。显然,它可以创造尽可能多的混乱。



整个想法是错误的。你不能覆盖属性 Items ,因为它不是虚拟的:

http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.items.aspx [< a href =http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.items.aspxtarget =_ blanktitle =New Window> ^ ] ,

http://msdn.microsoft .com / zh-cn / library / system.windows.forms.listbox.items.aspx [ ^ ]。



(不幸的是,你没有显示确切类型的 ListBox ,但是有不相关的类具有这样的名称。在提问时,您总是需要显示相关类型的完全限定名称。)



-S A
Please look at your code samples: I numbered them #1.. #3.

Problem #1:
Not a problem; this is correct behavior.

Problems #2 and #3:
The are stemmed from the fact that you have hidden Items property by adding new public ObjectCollectionEx Items. From this moment, you have two collections of items. If you use, say, inherited Add, you add some item to the inherited correction. But when you try to get access the item using the Items property, you access your new collection and cannot access the inherited one. Apparently, it can create as much mess as it can.

The whole idea is wrong. You cannot override the property Items, because it's not virtual:
http://msdn.microsoft.com/en-us/library/system.windows.controls.itemscontrol.items.aspx[^],
http://msdn.microsoft.com/en-us/library/system.windows.forms.listbox.items.aspx[^].

(Unfortunately, you did not show exact type of ListBox, but there are unrelated classes with such name. You always need to show fully-qualified names of relevant types when asking questions.)

—SA


您错过了一个重要的观点,即告诉列表框它有一个新的集合。为此,您必须在 ListBox.CreateItemCollection 中覆盖并创建新集合。一旦完成,SelectedIndex,SelectedItem和FindString问题就会消失。



我会尝试这样的事情:

You've missed an important point which is to tell the list box that it has a new collection. To do that you must override and create the new collection within ListBox.CreateItemCollection. Once that's done, the SelectedIndex, SelectedItem and FindString problems should go away.

I'd try something like this:
public class ObjectCollectionEx : ListBox.ObjectCollection {
  // duplicate the original constructors
  public ObjectCollectionEx(ListBox owner) : base(owner) { }
  public ObjectCollectionEx(ListBox owner, ListBox.ObjectCollection value) : base(owner, value) { }
  public ObjectCollectionEx(ListBox owner, object[] value) : base(owner, value) { }

  public new int Add(Object item) {
    return base.Add(MessWithObject(item));
  }

  // Make it visibly obvious that the new collection is being used!
  private Object MessWithObject(Object item) {
    return String.Format("{0} ({1})", item, item.GetType());
  }
}

public class ListBoxEx : ListBox {
  protected override ListBox.ObjectCollection CreateItemCollection() {
    return new ObjectCollectionEx(this);
  }

  public new ObjectCollectionEx Items {
    get { return (ObjectCollectionEx)base.Items; }
  }
}



艾伦。


Alan.


我想我经历过顿悟。如果有其他人感兴趣,请按以下方式:



我将不得不使用VB 6.0旧版的SendMessage()函数覆盖默认属性SelectedIndex :

I think I've experienced an epiphany. In case anybody else is interested, here's how:

I will have to override the default property "SelectedIndex" using the SendMessage() function of the olden days of VB 6.0:
public class ListBoxEx : ListBox
{
    // just supplement the above class with the properties / methods below... 

    [DllImport("USER32.DLL")]
    private static extern int SendMessage(IntPtr hWnd, uint message, int wParam, string lParam);
    [DllImport("USER32.DLL")]
    private static extern int SendMessage(IntPtr hWnd, uint message, int wParam, int lParam);
    [DllImport("USER32.DLL", CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr hWnd, uint message, int wParam, StringBuilder lParam);

    private const int LB_FINDSTRING = 0x018F;
    private const int LB_FINDSTRINGEXACT = 0x1A2;
    private const int LB_SETCURSEL = 0x0186;
    private const int LB_GETCURSEL = 0x0188;
    private const int LB_GETTEXT = 0x0189;

    ...

    new public int FindString(string s)
    {
        return SendMessage(this.Handle, LB_FINDSTRING, -1, s);
    }

    new public int FindStringExact(string s)
    {
        return SendMessage(this.Handle, LB_FINDSTRINGEXACT, -1, s);
    }

    new public int SelectedIndex
    {
        get
        {
            return SendMessage(this.Handle, LB_GETCURSEL, 0, 0);
        }
        set
        {
            SendMessage(this.Handle, LB_SETCURSEL, value, 0);
        }
    }

    new public object SelectedItem
    {
        get
        {
            StringBuilder s = new StringBuilder ( 256 );    // clean this up call LB_GETTEXTLEN first!
            SendMessage(this.Handle, LB_GETTEXT, this.SelectedIndex, s);
            return s;
        }
        set
        {
            this.SelectedIndex = this.FindStringExact(value.ToString());
        }
    }
}





是的,代码是kludgy,尤其是。考虑到你还必须定义SelectedValue,SelectedIndices等属性,但那些我还不想解决这些问题。它现在只需要做,除非有人给我们提供更好,更简单的解决方案。





啊,我觉得阿基米德= P



Yes, the code is kludgy, esp. considering that you'd also have to define the SelectedValue, SelectedIndices, etc. properties, but those I don't feel like tackling those yet. It will just have to do for now, unless someone here presents us with a better, simpler solution.


Ahh, I feel like Archimedes =P


这篇关于继承ListBox.ObjectCollection类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆