سؤال

أنا عالقة في .NET 2.0 Windows Forms.

أنها لا تبدو مثل القدرة على تحديد العقد متعددة موجودة في مستوى TreeView التحكم.

أنا أحاول أن أفعل هذا السياق اختيار القائمة.حتى تحقق الصناديق ليست مقبولة واجهة المستخدم النموذج هنا.

ما هي أفضل طريقة لتقديم هذا ضروري جدا وظيفة ؟

هل كانت مفيدة؟

المحلول

ولقد فعلنا ذلك في مشروع WTL مرة واحدة، ولكن العمل الأساسي المطلوب هو الشيء نفسه بالنسبة .NET. لتحقيق السيطرة شجرة التحديد متعددة، وسوف تحتاج لرسم عناصر الشجرة نفسك وتجاوز لوحة المفاتيح والماوس التعامل معها. سوف تحتاج أيضا إلى الحفاظ على القائمة الخاصة بك من العناصر التي تم تحديدها.

لا تنسى أن تنظر في قواعد الاختيار (والآباء والأبناء يسمح، على سبيل المثال)، و لا تنسى لتنفيذ اختصارات لوحة المفاتيح بما في ذلك اختيار باستخدام السيطرة، التحول، والسيطرة + التحول، وكذلك المسافة ل اختيار / إلغاء تحديد.

نصائح أخرى

هي خانات الخيار ؟ أو هل تريد تحديد مثل تحصل في قائمة الصندوق ؟

  • خانات يتم بناؤها في
  • حدد مثلك في مربع قائمة يتطلب مخصص شجرة التحكم

هناك متعددة حدد شجرة التحكم المتاحة على CodeProject:متعدد حدد طريقة عرض الشجرة

وكنت قد ننظر في حل 3rd الطرف. و Infragistics شجرة يفعل هذا. غير حرة، ولكن الوقت الذي يقضيه في محاولة لإيجاد حل ليست حقا حرة أيضا.

ورمز أدناه سوف يسمح لك لضبط لون الخلفية التي تستخدمها، لضمان أن يتم تسليط الضوء عن العقد المحدد.

protected override void WndProc(ref Message m)
{
    switch (m.Msg) {
        // WM_REFLECT is added because WM_NOTIFY is normally sent just
        // to the parent window, but Windows.Form will reflect it back
        // to us, MFC-style.
        case Win32.WM_REFLECT + Win32.WM_NOTIFY: {
            Win32.NMHDR nmhdr = (Win32.NMHDR)m.GetLParam(typeof(Win32.NMHDR));
            switch((int)nmhdr.code) {
                case Win32.NM_CUSTOMDRAW:
                    base.WndProc(ref m);
                    Win32.NMTVCUSTOMDRAW nmTvDraw = (Win32.NMTVCUSTOMDRAW)m.GetLParam(typeof(Win32.NMTVCUSTOMDRAW));
                    switch (nmTvDraw.nmcd.dwDrawStage) {
                        case Win32.CDDS_ITEMPREPAINT:
                            // Find the node being painted.
                            TreeNode n = TreeNode.FromHandle(this, nmTvDraw.nmcd.lItemlParam);
                            if (allSelected.Contains(n))
                                // Override its background colour.
                                nmTvDraw.clrTextBk = ColorTranslator.ToWin32(SystemColors.Highlight);
                            m.Result = (IntPtr)Win32.CDRF_DODEFAULT;  // Continue rest of painting as normal
                            break;
                    }
                    Marshal.StructureToPtr(nmTvDraw, m.LParam, false);  // copy changes back
                    return;
            }
            break;
        }
    }
    base.WndProc(ref m);
}

// WM_NOTIFY notification message header.
[System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
public class NMHDR
{
    private IntPtr hwndFrom;
    public IntPtr idFrom;
    public uint code;
}

[StructLayout(LayoutKind.Sequential)]
public struct NMCUSTOMDRAW
{
    public NMHDR hdr;
    public int dwDrawStage;
    public IntPtr hdc;
    public RECT rc;
    public IntPtr dwItemSpec;
    public int uItemState;
    public IntPtr lItemlParam;
}

[StructLayout(LayoutKind.Sequential)]
public struct NMTVCUSTOMDRAW
{
    public NMCUSTOMDRAW nmcd;
    public int clrText;
    public int clrTextBk;
    public int iLevel;
}

public const int CDIS_SELECTED = 0x0001;
public const int CDIS_FOCUS = 0x0010;
public const int CDDS_PREPAINT = 0x00000001;
public const int CDDS_POSTPAINT = 0x00000002;
public const int CDDS_PREERASE = 0x00000003;
public const int CDDS_POSTERASE = 0x00000004;
public const int CDDS_ITEM = 0x00010000;  // item specific 
public const int CDDS_ITEMPREPAINT = (CDDS_ITEM | CDDS_PREPAINT);
public const int CDDS_ITEMPOSTPAINT = (CDDS_ITEM | CDDS_POSTPAINT);
public const int CDDS_ITEMPREERASE = (CDDS_ITEM | CDDS_PREERASE);
public const int CDDS_ITEMPOSTERASE = (CDDS_ITEM | CDDS_POSTERASE);
public const int CDDS_SUBITEM = 0x00020000;
public const int CDRF_DODEFAULT = 0x00000000;
public const int CDRF_NOTIFYITEMDRAW = 0x00000020;
public const int CDRF_NOTIFYSUBITEMDRAW = 0x00000020;  // flags are the same, we can distinguish by context

public const int WM_USER = 0x0400;
public const int WM_NOTIFY = 0x4E;
public const int WM_REFLECT = WM_USER + 0x1C00;

وأبسط حل سيكون لتمديد تحكم TreeView القائمة التي يتم شحنها مع إطار وتجاوز الأساليب OnBeforeSelect وOnAfterSelect مع المنطق لالتقاط تحديدات متعددة.

ويمكن الاطلاع على مثال هنا: http://www.arstdesign.com/articles/treeviewms هتمل

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top