[AntdUI] 05 Select等选择类控件的创建

nanyi 13小时前 39 v 1.0.0.0 2026-06-15

antdUI中的Select控件,控件形式类似于aardio中的combobox下拉框控件,用于有较多选项填充的选择,但只能择其一,而SelectMultiple可以理解为Select+Checkbox加强版,将所有的Checkbox选项放置于一个input中,可以进行多项选择。

antdUI的Dropdown控件更像是aardio中的popmenu,点击控件弹出菜单项选择进行操作。

本演示代码主要包括了对Select、SelectMultiple、Dropdown、ColorPicker、Tree、Tab几个控件的基础绘制和操作事件的演示。

import win.ui;
import dotNet.AntdUI;
import dotNet;
/*DSG{{*/
var winform = win.form(text="AntdUI Tabs / Select / Dropdown / ColorPicker / Tree Demo";right=900;bottom=650;border="thin")
winform.add(
custom_base={cls="custom";left=0;top=0;right=902;bottom=650;ah=1;aw=1;db=1;disabled=1;dl=1;dr=1;dt=1;hide=1;z=1};
custom_tabs={cls="custom";left=20;top=20;right=880;bottom=610;db=1;dl=1;dr=1;dt=1;z=2}
)
/*}}*/

var baseForm = AntdUI.BaseForm();
baseForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
baseForm.Dock = System.Windows.Forms.DockStyle.Fill;
dotNet.setParent(baseForm, winform.custom_base);

var fontTitle = System.Drawing.Font("Microsoft YaHei", 14, System.Drawing.FontStyle.Bold);
var fontNormal = System.Drawing.Font("Microsoft YaHei", 10);
var fontTip = System.Drawing.Font("Microsoft YaHei", 9);

var showSuccess = function(text){
    AntdUI.Message.success(baseForm, text);
}

var addLabel = function(parent,text,x,y,w,h,font){
    var label = AntdUI.Label();
    label.Text = text;
    label.Font = font || fontNormal;
    label.SetBounds(x,y,w,h);
    parent.Controls.Add(label);
    return label;
}

var addSectionTitle = function(parent,text,x,y){
    return addLabel(parent,text,x,y,480,34,fontTitle);
}

var addSelectItem = function(selCtrl,text,value){
    selCtrl.Items.Add(AntdUI.SelectItem(text,value));
}

var addGroup = function(selCtrl,title,items){
    var group = AntdUI.GroupSelectItem(title);
    var list = dotNet.list(System.Object);
    for(i,item in items){
        if(type(item) == "table"){
            list.Add(AntdUI.SelectItem(item.text,item.value));
        }
        else {
            list.Add(item);
        }
    }
    group.Sub = list;
    selCtrl.Items.Add(group);
    return group;
}

var addDropdownSubItem = function(parentItem,items){
    var list = dotNet.list(System.Object);
    for(i,item in items){
        if(type(item) == "table"){
            list.Add(AntdUI.SelectItem(item.text,item.value));
        }
        else {
            list.Add(item);
        }
    }
    parentItem.Sub = list;
    return parentItem;
}

var describeValue = function(sender,e){
    var text = tostring(sender.Text);
    var value = null;

    if(e){
        value = e.get_Value();
    }

    if(!value){
        value = sender.SelectedValue;
    }

    if(value){
        return text ++ " / value: " ++ tostring(value);
    }

    return text;
}

var describeMultiValue = function(sender,e){
    var values = null;

    if(e){
        values = e.get_Value();
    }

    if(!values){
        values = sender.SelectedValue;
    }

    var arr = [];

    if(values){
        // SelectMultiple.SelectedValue 是 .NET 的 System.Object[],索引从 0 开始
        if(values.Length !== null){
            for(i=0; values.Length-1; 1){
                var v = values.GetValue(i);
                if(v !== null){
                    table.push(arr,tostring(v));
                }
            }
        }
        else {
            // 兜底:如果某些版本返回 aardio table
            for(i,v in values){
                if(v !== null){
                    table.push(arr,tostring(v));
                }
            }
        }
    }
    if(#arr){
        return string.join(arr,", ");
    }
    return "";
}



var colorToHex = function(color){
    var n = tonumber(color);
    return string.format("#%02X%02X%02X",(n >> 16) & 0xFF,(n >> 8) & 0xFF,n & 0xFF);
}

var setColorPreview = function(panel,color){
    panel.BackColor = color;
}

var treeNode = function(text,name,children){
    var item = AntdUI.TreeItem(text);
    item.Name = name;
    item.Tag = name;
    if(children){
        for(i,child in children){
            item.Sub.Add(child);
        }
    }
    return item;
}

// ---------- Tabs ----------
var tabs = AntdUI.Tabs();
tabs.Dock = System.Windows.Forms.DockStyle.Fill;
tabs.Font = fontNormal;
tabs.Type = AntdUI.TabType.Line;
dotNet.setParent(tabs, winform.custom_tabs);

var pageSelect = AntdUI.TabPage();
pageSelect.Text = "Select";
pageSelect.Dock = System.Windows.Forms.DockStyle.Fill;

var pageDropdown = AntdUI.TabPage();
pageDropdown.Text = "Dropdown";
pageDropdown.Dock = System.Windows.Forms.DockStyle.Fill;

var pageColorPicker = AntdUI.TabPage();
pageColorPicker.Text = "ColorPicker";
pageColorPicker.Dock = System.Windows.Forms.DockStyle.Fill;

var pageTree = AntdUI.TabPage();
pageTree.Text = "Tree";
pageTree.Dock = System.Windows.Forms.DockStyle.Fill;

var pageInfo = AntdUI.TabPage();
pageInfo.Text = "Tabs Info";
pageInfo.Dock = System.Windows.Forms.DockStyle.Fill;

var pageMore = AntdUI.TabPage();
pageMore.Text = "More";
pageMore.Dock = System.Windows.Forms.DockStyle.Fill;

tabs.Pages.Add(pageSelect);
tabs.Pages.Add(pageDropdown);
tabs.Pages.Add(pageColorPicker);
tabs.Pages.Add(pageTree);
tabs.Pages.Add(pageInfo);
tabs.Pages.Add(pageMore);

tabs.SelectedIndexChanged = function(sender,e){
    if(e.Value > 0){
        showSuccess("Current tab: " + sender.SelectedTab.Text);
    }
}

// ---------- Page 1: Select / SelectMultiple ----------
addSectionTitle(pageSelect,"Select",30,30);
addLabel(pageSelect,"Basic select",30,82,150,28,fontNormal);

var selectBasic = AntdUI.Select();
selectBasic.SetBounds(190,74,260,44);
selectBasic.PlaceholderText = "Choose a fruit";
selectBasic.AllowClear = true;
selectBasic.ListAutoWidth = true;
selectBasic.Font = fontNormal;
selectBasic.Items.Add("Apple");
selectBasic.Items.Add("Banana");
selectBasic.Items.Add("Orange");
selectBasic.Items.Add("Mango");
selectBasic.SelectedValueChanged = function(sender,e){
    var value = e.get_Value();

    if(value){
        showSuccess("Selected fruit: " ++ describeValue(sender,e));
    }
}

pageSelect.Controls.Add(selectBasic);

addLabel(pageSelect,"Grouped select",30,142,150,28,fontNormal);

var selectCity = AntdUI.Select();
selectCity.SetBounds(190,134,300,44);
selectCity.PlaceholderText = "Choose a city";
selectCity.PrefixText = "City";
selectCity.PrefixFore = 0xFF6D6D6D;
selectCity.AllowClear = true;
selectCity.ListAutoWidth = true;
selectCity.Font = fontNormal;
addGroup(selectCity,"China",[
    {text="Beijing";value="CN-BJ"},
    {text="Shanghai";value="CN-SH"},
    {text="Hangzhou";value="CN-HZ"}
]);
selectCity.Items.Add(AntdUI.DividerSelectItem());
addGroup(selectCity,"Japan",[
    {text="Tokyo";value="JP-TYO"},
    {text="Osaka";value="JP-OSA"}
]);
selectCity.SelectedValueChanged = function(sender,e){
    var value = e.get_Value();

    if(value){
        showSuccess("Selected city: " ++ describeValue(sender,e));
    }
    else {
        showSuccess("Selected city cleared");
    }
}

pageSelect.Controls.Add(selectCity);

addLabel(pageSelect,"Status select",30,202,150,28,fontNormal);

var selectStatus = AntdUI.Select();
selectStatus.SetBounds(190,194,260,44);
selectStatus.PlaceholderText = "Choose status";
selectStatus.AllowClear = true;
selectStatus.Font = fontNormal;
selectStatus.Items.Add(AntdUI.SelectItem(1,"Online","online"));
selectStatus.Items.Add(AntdUI.SelectItem(2,"Busy","busy"));
selectStatus.Items.Add(AntdUI.SelectItem(0,"Offline","offline"));
selectStatus.SelectedValueChanged = function(sender,e){
    var value = e.get_Value();

    if(value){
        showSuccess("Selected status: " ++ describeValue(sender,e));
    }
    else {
        showSuccess("Selected status cleared");
    }
}

pageSelect.Controls.Add(selectStatus);

addSectionTitle(pageSelect,"SelectMultiple",30,282);
addLabel(pageSelect,"Basic multiple",30,334,150,28,fontNormal);

var multiBasic = AntdUI.SelectMultiple();
multiBasic.SetBounds(190,326,360,44);
multiBasic.PlaceholderText = "Choose technologies";
multiBasic.AllowClear = true;
multiBasic.TagBordered = true;
multiBasic.MaxChoiceCount = 3;
multiBasic.Font = fontNormal;
multiBasic.Items.Add("aardio");
multiBasic.Items.Add("C#");
multiBasic.Items.Add("WinForm");
multiBasic.Items.Add("WebView2");
multiBasic.Items.Add("SQLite");
multiBasic.SelectedValueChanged = function(sender,e){
    var text = describeMultiValue(sender,e);

    if(text){
        showSuccess("Selected technologies: " ++ text);
    }
    else {
        showSuccess("Selected technologies cleared");
    }
}


pageSelect.Controls.Add(multiBasic);

addLabel(pageSelect,"Check mode",30,394,150,28,fontNormal);

var multiCheck = AntdUI.SelectMultiple();
multiCheck.SetBounds(190,386,420,44);
multiCheck.PlaceholderText = "Choose permissions";
multiCheck.PrefixText = "Role";
multiCheck.PrefixFore = 0xFF6D6D6D;
multiCheck.AllowClear = true;
multiCheck.CheckMode = true;
multiCheck.MaxChoiceCount = 4;
multiCheck.Font = fontNormal;
addGroup(multiCheck,"Basic",[
    {text="Read";value="read"},
    {text="Write";value="write"}
]);
addGroup(multiCheck,"Admin",[
    {text="Create";value="create"},
    {text="Delete";value="delete"},
    {text="Publish";value="publish"}
]);
multiCheck.SelectedValueChanged = function(sender,e){
    var text = describeMultiValue(sender,e);

    if(text){
        showSuccess("Selected permissions: " ++ text);
    }
    else {
        showSuccess("Selected permissions cleared");
    }
}


pageSelect.Controls.Add(multiCheck);

addLabel(
    pageSelect,
    "Properties shown: PlaceholderText, AllowClear, PrefixText, ListAutoWidth, grouped options, divider, MaxChoiceCount, TagBordered, CheckMode.",
    30,480,760,50,fontTip
);

// ---------- Page 2: Dropdown ----------
addSectionTitle(pageDropdown,"Dropdown",30,30);
addLabel(pageDropdown,"Basic dropdown",30,88,160,28,fontNormal);

var dropdownBasic = AntdUI.Dropdown();
dropdownBasic.SetBounds(200,78,180,44);
dropdownBasic.Text = "Actions";
dropdownBasic.Font = fontNormal;
dropdownBasic.Type = AntdUI.TTypeMini.Primary;
dropdownBasic.Placement = AntdUI.TAlignFrom.BL;
dropdownBasic.Items.Add(AntdUI.SelectItem("New File","new"));
dropdownBasic.Items.Add(AntdUI.SelectItem("Open File","open"));
dropdownBasic.Items.Add(AntdUI.SelectItem("Save","save"));
dropdownBasic.Items.Add(AntdUI.DividerSelectItem());
dropdownBasic.Items.Add(AntdUI.SelectItem("Exit","exit"));
dropdownBasic.ItemClick = function(sender,e){
    showSuccess("Dropdown action: " + tostring(e.Value));
}
pageDropdown.Controls.Add(dropdownBasic);

addLabel(pageDropdown,"Nested menu",30,158,160,28,fontNormal);

var dropdownNested = AntdUI.Dropdown();
dropdownNested.SetBounds(200,148,200,44);
dropdownNested.Text = "Export";
dropdownNested.Font = fontNormal;
dropdownNested.ShowArrow = true;
dropdownNested.Placement = AntdUI.TAlignFrom.BL;
dropdownNested.Items.Add(AntdUI.SelectItem("Quick Export","quick"));
dropdownNested.Items.Add(AntdUI.DividerSelectItem());

var itemExport = AntdUI.SelectItem("Export As","export");
addDropdownSubItem(itemExport,[
    {text="PDF document";value="pdf"},
    {text="PNG image";value="png"},
    {text="Excel workbook";value="xlsx"}
]);
dropdownNested.Items.Add(itemExport);

var itemShare = AntdUI.SelectItem("Share To","share");
addDropdownSubItem(itemShare,[
    {text="Email";value="email"},
    {text="Cloud Drive";value="cloud"}
]);
dropdownNested.Items.Add(itemShare);

dropdownNested.ItemClick = function(sender,e){
    showSuccess("Nested dropdown: " + tostring(e.Value));
}
pageDropdown.Controls.Add(dropdownNested);

addLabel(pageDropdown,"Trigger by hover",30,228,160,28,fontNormal);

var dropdownHover = AntdUI.Dropdown();
dropdownHover.SetBounds(200,218,200,44);
dropdownHover.Text = "Hover me";
dropdownHover.Font = fontNormal;
dropdownHover.Trigger = AntdUI.Trigger.Hover;
dropdownHover.Placement = AntdUI.TAlignFrom.BL;
dropdownHover.Items.Add(AntdUI.SelectItem("Profile","profile"));
dropdownHover.Items.Add(AntdUI.SelectItem("Settings","settings"));
dropdownHover.Items.Add(AntdUI.SelectItem("Logout","logout"));
dropdownHover.ItemClick = function(sender,e){
    showSuccess("Hover dropdown: " + tostring(e.Value));
}
pageDropdown.Controls.Add(dropdownHover);

addLabel(pageDropdown,"Toggle style",30,298,160,28,fontNormal);

var dropdownToggle = AntdUI.Dropdown();
dropdownToggle.SetBounds(200,288,220,44);
dropdownToggle.Text = "Toggle Dropdown";
dropdownToggle.Font = fontNormal;
dropdownToggle.Type = AntdUI.TTypeMini.Success;
dropdownToggle.ToggleType = AntdUI.TTypeMini.Warn;
dropdownToggle.Items.Add(AntdUI.SelectItem("Normal item","normal"));
dropdownToggle.Items.Add(AntdUI.SelectItem("Toggle item","toggle"));
dropdownToggle.ToggleChanged = function(sender,e){
    showSuccess("Dropdown toggle: " + tostring(e.Value));
}
dropdownToggle.ItemClick = function(sender,e){
    showSuccess("Toggle dropdown item: " + tostring(e.Value));
}
pageDropdown.Controls.Add(dropdownToggle);

addLabel(
    pageDropdown,
    "Properties shown: Items, ItemClick, Type, Placement, Trigger.Hover, ShowArrow, nested Sub items, ToggleType and ToggleChanged.",
    30,390,780,50,fontTip
);

// ---------- Page 3: ColorPicker ----------
addSectionTitle(pageColorPicker,"ColorPicker",30,30);
addLabel(pageColorPicker,"Basic color",30,88,160,28,fontNormal);

var colorBasic = AntdUI.ColorPicker();
colorBasic.SetBounds(200,78,220,44);
colorBasic.Text = "";
colorBasic.Font = fontNormal;
colorBasic.Value = 0xFF167CD9;
colorBasic.ShowText = true;
colorBasic.ShowSymbol = true;
colorBasic.AllowClear = true;
pageColorPicker.Controls.Add(colorBasic);


colorBasic.ValueChanged = function(sender,e){
    showSuccess("Theme color: " + colorToHex(e.Value));
}

addLabel(
    pageColorPicker,
    "Properties shown: Value, ValueChanged, ShowText, ShowSymbol, AllowClear, Round, Placement, ShowReset, ShowClose and disabled state.",
    30,200,780,50,fontTip
);

// ---------- Page 4: Tree ----------
addSectionTitle(pageTree,"Tree",30,30);
addLabel(pageTree,"Left click selects, checkbox checks, right-click a tree item to edit its text.",30,64,650,28,fontTip);

var tree = AntdUI.Tree();
tree.SetBounds(30,100,420,410);
tree.Font = fontNormal;
tree.Checkable = true;
tree.Multiple = true;
tree.BlockNode = true;
tree.Radius = 6;
tree.Gap = 4;
tree.EmptyText = "No tree data";
pageTree.Controls.Add(tree);

var nodeMain = treeNode("main.aardio","main");
nodeMain.Checked = true;

var nodeViews = treeNode("views","views",[
    treeNode("home.aardio","home"),
    treeNode("settings.aardio","settings"),
    treeNode("about.aardio","about")
]);

var nodeAssets = treeNode("assets","assets",[
    treeNode("logo.png","logo"),
    treeNode("theme.json","theme")
]);

var nodeSrc = treeNode("src","src",[
    nodeMain,
    nodeViews,
    nodeAssets
]);

var nodeDocs = treeNode("docs","docs",[
    treeNode("README.md","readme"),
    treeNode("CHANGELOG.md","changelog")
]);

var nodeRoot = treeNode("AntdUI Demo Project","project",[
    nodeSrc,
    nodeDocs,
    treeNode("package.json","package")
]);

nodeRoot.Expand = true;
nodeSrc.Expand = true;
tree.Items.Add(nodeRoot);

var btnExpandAll = AntdUI.Button();
btnExpandAll.SetBounds(490,104,140,42);
btnExpandAll.Text = "Expand All";
btnExpandAll.Font = fontNormal;
btnExpandAll.Type = AntdUI.TTypeMini.Primary;
pageTree.Controls.Add(btnExpandAll);

var btnCollapseAll = AntdUI.Button();
btnCollapseAll.SetBounds(650,104,140,42);
btnCollapseAll.Text = "Collapse All";
btnCollapseAll.Font = fontNormal;
pageTree.Controls.Add(btnCollapseAll);

var lblSelected = addLabel(pageTree,"Selected: AntdUI Demo Project",490,170,330,32,fontNormal);
var lblChecked = addLabel(pageTree,"Checked nodes: 1",490,210,330,32,fontNormal);
var lblExpand = addLabel(pageTree,"Expand event: ready",490,250,330,32,fontTip);

addLabel(
    pageTree,
    "Tree properties shown: Items, TreeItem.Sub, Checkable, Multiple, BlockNode, ExpandAll, SelectChanged, CheckedChanged, BeforeExpand, AfterExpand and NodeMouseClick.",
    490,300,330,100,fontTip
);

// 重要:AntdUI.Tree 的事件参数在 aardio 中建议用 get_Item/get_Value/get_Button 读取。
// 不要直接写 e.Item / e.Value / e.Button,否则会造成事件抛错。
var getTreeEventItem = function(e){
    return e.get_Item();
}

var getTreeEventValue = function(e){
    return e.get_Value();
}

var isRightMouseButton = function(e){
    return tonumber(e.get_Button()) == tonumber(System.Windows.Forms.MouseButtons.Right);
}

var updateCheckedLabel = function(){
    var checkedItems = tree.GetCheckeds(true);
    lblChecked.Text = "Checked nodes: " + tostring(checkedItems.Count);
}

var editTreeItem = function(item){
    if(!item) return;

    tree.Select(item,true);

    var input = AntdUI.Input();
    input.Text = item.Text;
    input.PlaceholderText = "Input tree item text";
    input.SetBounds(0,0,320,44);

    var cfg = AntdUI.Modal.config(baseForm,"Edit tree item",input);
    cfg.SetOk("Save");
    cfg.SetCancel("Cancel");
    cfg.SetWidth(420);
    cfg.SetInput(input);

    var result = AntdUI.Modal.open(cfg);
    if(result == System.Windows.Forms.DialogResult.OK){
        var newText = string.trim(input.Text);
        if(newText){
            item.Text = newText;
            tree.Refresh();
            lblSelected.Text = "Selected: " + newText;
            showSuccess("Tree item renamed: " + newText);
        }
    }
}

btnExpandAll.Click = function(sender,e){
    // 使用显式重载,避免 .NET 重载解析歧义。
    tree.ExpandAll(tree.Items,true);
    tree.Refresh();

    lblExpand.Text = "Expand event: expanded all";
    showSuccess("Tree expanded all");
}

btnCollapseAll.Click = function(sender,e){
    // 使用显式重载,避免 .NET 重载解析歧义。
    tree.ExpandAll(tree.Items,false);
    tree.Refresh();

    lblExpand.Text = "Expand event: collapsed all";
    showSuccess("Tree collapsed all");
}

tree.SelectChanged = function(sender,e){
    var item = getTreeEventItem(e);
    if(item){
        lblSelected.Text = "Selected: " + item.Text;
    }
}

tree.CheckedChanged = function(sender,e){
    updateCheckedLabel();

    var item = getTreeEventItem(e);
    if(item){
        lblExpand.Text = "Checked: " + item.Text + " = " + tostring(getTreeEventValue(e));
    }
}

tree.BeforeExpand = function(sender,e){
    var item = getTreeEventItem(e);
    if(item){
        lblExpand.Text = (getTreeEventValue(e) ? "Expanding: " : "Collapsing: ") + item.Text;
    }
}

tree.AfterExpand = function(sender,e){
    var item = getTreeEventItem(e);
    if(item){
        lblExpand.Text = (getTreeEventValue(e) ? "Expanded: " : "Collapsed: ") + item.Text;
    }
}

tree.NodeMouseClick = function(sender,e){
    var item = getTreeEventItem(e);
    if(item && isRightMouseButton(e)){
        editTreeItem(item);
    }
}

tree.NodeMouseDoubleClick = function(sender,e){
    var item = getTreeEventItem(e);
    if(item){
        showSuccess("Tree double clicked: " + item.Text);
    }
}

updateCheckedLabel();


// ---------- Page 5: Tabs info ----------
addSectionTitle(pageInfo,"Tabs",30,30);
addLabel(
    pageInfo,
    "This page demonstrates AntdUI.Tabs and TabPage. The first tab contains Select and SelectMultiple examples.",
    30,85,760,32,fontNormal
);
addLabel(
    pageInfo,
    "The second, third and fourth tabs demonstrate Dropdown, ColorPicker and Tree controls.",
    30,128,760,32,fontNormal
);
addLabel(
    pageInfo,
    "Tabs properties used: Type, Pages, SelectedIndexChanged, TabPage.Text and Dock.",
    30,171,760,32,fontTip
);

// ---------- Page 6: More ----------
addSectionTitle(pageMore,"More examples",30,30);
addLabel(
    pageMore,
    "You can add more AntdUI controls into each TabPage by page.Controls.Add(control).",
    30,85,760,32,fontNormal
);

// ---------- 资源释放 ----------
winform.onClose = function(){
    fontTitle.Dispose();
    fontNormal.Dispose();
    fontTip.Dispose();
}

winform.wndproc = function(hwnd, message, wParam, lParam){
    if( message == 0x0216 || message == 0x0003 ){
        if(baseForm){
            var hwndBase = baseForm.Handle;
            if(hwndBase){
                // 向 .NET Form 发送winform移动消息
                ::User32.SendMessage(hwndBase, 0x0003/*_WM_MOVE*/, 0, 0);
            }
        }
    }
}

winform.show();
win.loopMessage();

下期预告:Steps/TimeLine步骤条和时间轴控件的创建


最新回复 (2)
  • lcj21 8小时前
    0 2

    效果不错!

  • lcj21 7小时前
    0 3
    出一期换背景的教程,背景如何换色或者用图片做背景
返回