2010-01-20 69 views
1

我正在創建一個可以繪製分隔符的自定義組合框。所以,我重寫OnDrawItem()和OnMeasureItem()方法。
問題是OnMeasureItem()僅在數據源更改時被調用一次。因此,如果我想稍後指定分隔項目,我需要重新測量它的高度(因爲帶分隔符的項目應該更高),但似乎所有可能導致項目高度被重新測量的方法都是私有的,所以我不能稱它們爲。
我不知道是否很容易理解我上面寫的東西,所以我會重複我需要的東西:
每次我需要重新測量項目高度(必須調用OnMeasureItem())時,我指定項目應該用分隔符繪製。如何使組合框重新測量項目高度?

separatorableComboBox.DataSource = customers; 
// and now I want the third customer in the list to be drawn with a separator, 
// so it needs to be taller and therefore OnMeasureItem() should be called 
separatorableComboBox.SpecifySeparatorItem(customers[2]); 

UPD。夥計們,調用RefreshItems()的作品,但它非常慢(我的機器上> 20毫秒),有更快的方法嗎?
UPD2。現在我正在使用SendMessage(...,CB_SETITEMHEIGHT,...);方法建議serge_gubenko。但是我只是好奇,是否有一種快速的方式來完成.NET的任務(或者更具體地說ComboBox類本身)?

回答

3

爲了澄清,我假設您使用OwnerDrawVariable樣式爲您的組合框。如果我理解正確你的問題,有幾個方法可以做到你所需要的:

  • 調用組合框的RefreshItems方法,這將重建項目,並觸發onMeasureItem事件爲每個項目。此方法是受保護的ComboBox類,所以下面是如何,你可以使用反射做一個例子:
MethodInfo method = comboBox1.GetType().GetMethod(
     "RefreshItems", BindingFlags.Instance | BindingFlags.NonPublic); 
    if (method != null) method.Invoke(comboBox1, null); 
  • 發送CB_SETITEMHEIGHT消息控制與項目的新高度,只要你要改變它:
public const int CB_SETITEMHEIGHT = 0x0153; 
    [DllImport("user32.dll", CharSet = CharSet.Auto)] 
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, int wParam, int lParam); 
    ... 
    // this will set height to 100 for the item with index 2 
    SendMessage(comboBox1.Handle, CB_SETITEMHEIGHT, 2, 100); 

希望這會有所幫助,至於

+0

發送消息的過程非常快,但我只是很好奇,是否有更正確和更快速的方式來完成託管代碼(更具體地說可能是使用ComboBox類)的任務? – nightcoder 2010-01-20 22:14:48

+0

使用winforms時,我不會擔心它太多,最終還是會有一個windows COMBOBOX控件(http://msdn.microsoft.com/en-us/library/bb775792(VS.85).aspx)運行你的形式;你可以用spy ++來檢查它。 ComboBox類在其UpdateItemHeight()方法中調整項目高度時使用相同的方法,該方法是私有的,因此您需要使用反射來調用它。至於RefreshItems,它完全重新加載項目列表。基本上它應該是相同的,將null設置爲其DataSource屬性,然後將其恢復爲以前的值 – 2010-01-21 01:18:52

4

您可以撥打ComboBox.RefreshItems()以提高MeasureItem()電話,要麼你對你的CustomCombo類SpecifySeparatorItem()內:

public void SpecifySeparatorItem(object arg) 
{ 
    //do some stuff 

    this.RefreshItems(); 

    //do some more stuff 
} 

,或者通過一個公共方法暴露ComboBox.RefreshItems(),您可以調用其他地方

public partial class CustomCombo : ComboBox 
{ 
    public CustomCombo() 
    { 
     InitializeComponent(); 
    } 

    protected override void OnMeasureItem(MeasureItemEventArgs e) 
    { 
     base.OnMeasureItem(e); 
    } 

    public void RaiseOnMeasureItem() 
    { 
     this.RefreshItems(); 
    } 
} 
+0

傢伙,呼籲RefreshItems()工作,但它非常慢(我的機器上> 20毫秒),有更快的方法嗎? – nightcoder 2010-01-20 21:45:48