Разрешаване на множествен избор в .NET TreeView

Заседнал съм в .NET 2.0 Windows Forms.

Не изглежда, че възможността за избиране на множество възли съществува в стандартния контрол TreeView.

Опитвам се да направя това за избор от контекстно меню. Така че квадратчетата за отметка не са приемлива парадигма на потребителския интерфейс тук.

Какъв е най-добрият начин да осигурите тази така необходима функционалност?


person Darcy Casselman    schedule 15.10.2008    source източник


Отговори (6)


Веднъж направихме това в WTL проект, но основната необходима работа е същата за .NET. За да постигнете дървовидна контрола с множествена селекция, ще трябва сами да начертаете дървовидните елементи и да отмените манипулирането на клавиатурата и мишката. Вие също ще трябва да поддържате свой собствен списък с избрани елементи.

Не забравяйте да вземете под внимание правилата за избор (разрешени ли са родители и деца, например) и не забравяйте да приложите клавишните комбинации, включително избор с помощта на Ctrl, Shift и Ctrl+Shift, както и интервала за избор/отмяна на избор .

person Jeff Yates    schedule 15.10.2008
comment
Можете сами да правите чертежа, като прихванете WM_NOTIFY и коригирате цвета на фона за избраните възли. Добавих отговор, за да мога да включа кода. - person Oliver Bock; 26.03.2012
comment
@OliverBock: Това със сигурност е най-простият начин, ако всичко, от което се нуждаете, е промяна на цвета на фона. - person Jeff Yates; 26.03.2012

TreeView.CheckBoxes

person Community    schedule 15.10.2008
comment
Това всъщност не е това, което търся. Всеки друг дървовиден изглед в Windows ви позволява да изберете няколко записа с ctrl и щракване. И премахването на контекстното меню от квадратчетата за отметка няма никакъв смисъл. - person Darcy Casselman; 15.10.2008
comment
Не мога да намеря пример за дървовиден изглед с ctrl-щракване никъде в стандартната среда на Windows OS. Можете ли да дадете пример? Съгласен съм, че контекстното меню от проверките не е много разумно, но не мисля, че очакването на потребителите да ctrl+щракнат също е така. (Много потребители имат проблеми с това според моя опит.) - person John Rudy; 15.10.2008
comment
За стандартния дървовиден изглед на Windows Forms по този начин избирате повече от един възел в дървото. - person ; 15.10.2008
comment
Добре, стандарт може да е грешната дума. Вземете например Solution Explorer във Visual Studio. - person Darcy Casselman; 15.10.2008
comment
Проблемът е, че стандартните контроли, с които можете да играете и използвате безплатно (тези, които се доставят с VS), не са непременно тези, които виждате да се използват в Windows. Имате три възможности 1) квадратчета за отметка 2) напишете своя собствена 3) купете такава. Гадно, знам. Лесно се прави в WPF! - person ; 15.10.2008

Опция ли са квадратчетата за отметка? или искате избора като в списъчно поле?

  • checkboxes are built in
  • select like you get in a list box requires a custom tree control

В CodeProject има налична дървовидна контрола с множество избори: Дървовиден изглед с множество избори

person Jay Mooney    schedule 15.10.2008

Най-простото решение би било да се разшири съществуващата контрола TreeView, доставена с рамката, и да се заменят методите OnBeforeSelect и OnAfterSelect с логика за улавяне на множество селекции.

Пример може да бъде намерен тук: http://www.arstdesign.com/articles/treeviewms.html

person timpeck    schedule 03.02.2011

Кодът по-долу ще ви позволи да коригирате цвета на фона, който използвате, за да сте сигурни, че всички избрани възли са маркирани.

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;
person Oliver Bock    schedule 25.03.2012

Може да разгледате решение на трета страна. Дървото Infragistics прави това. Не е безплатно, но времето, прекарано в опити за намиране на решение, също не е безплатно.

person Jon B    schedule 15.10.2008
comment
-1 : отне ми много по-малко от 5 минути, за да намеря прост безплатен и да го внедря в моето решение. Ето 2 примера: codeproject.com/KB/tree/MWTreeViewv2010.aspx , arstdesign.com/articles/treeviewms.html. Не е перфектно, но работи и може да се подобри, ако се ориентирате. - person synhershko; 03.02.2010
comment
@synhershko: Статиите са датирани съответно от 2004 г. и 2002 г., сигурен съм, че има по-добри начини да се приложи същото нещо днес. - person Neolisk; 19.09.2013
comment

Може би това се случва, защото в правилото за стил липсва точка и запетая в края? Така че трябва да бъде <span style="color:red;">

- person Larry; 15.10.2013