Skip to content

Implement DropDownList component with shared ListItem infrastructure#282

Merged
csharpfritz merged 5 commits into
devfrom
copilot/implement-dropdownlist-component
Jan 28, 2026
Merged

Implement DropDownList component with shared ListItem infrastructure#282
csharpfritz merged 5 commits into
devfrom
copilot/implement-dropdownlist-component

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Jan 28, 2026

Implements the DropDownList component to emulate ASP.NET Web Forms System.Web.UI.WebControls.DropDownList, rendering as an HTML <select> element with data binding and event support.

Implementation

Core Components

  • ListItem / ListItemCollection - Shared classes for list-based controls (CheckBoxList, RadioButtonList, ListBox will reuse)
  • DropDownList<TItem> - Generic component inheriting from DataBoundComponent<TItem> with IStyle support

Key Features

  • Static items via StaticItems parameter (ListItemCollection)
  • Data binding with DataTextField / DataValueField for complex objects
  • Two-way binding via @bind-SelectedValue
  • SelectedIndex tracking and SelectedItem accessor
  • OnSelectedIndexChanged event handler
  • Full styling support (BackColor, ForeColor, Font, CssClass, BorderStyle, etc.)

Usage

<!-- Static items -->
<DropDownList TItem="object" StaticItems="items" @bind-SelectedValue="selectedValue" />

<!-- Data-bound -->
<DropDownList TItem="Product"
              Items="products"
              DataTextField="Name"
              DataValueField="Id"
              @bind-SelectedValue="selectedId"
              OnSelectedIndexChanged="HandleChange" />

@code {
    private ListItemCollection items = new()
    {
        new ListItem("Select...", ""),
        new ListItem("Option One", "1"),
        new ListItem("Option Two", "2")
    };
}

Testing & Documentation

  • 11 unit tests covering static items, data binding, selection, events, styling
  • Documentation with Web Forms comparison and migration guide
  • Blazor and Web Forms sample pages
Original prompt

This section details on the original issue you should resolve

<issue_title>Implement DropDownList Component</issue_title>
<issue_description>## Overview

Implement the DropDownList Blazor component that emulates the ASP.NET Web Forms System.Web.UI.WebControls.DropDownList control. This is a commonly used selection control that renders as an HTML <select> element with <option> children.

Microsoft Docs Reference: https://docs.microsoft.com/en-us/dotnet/api/system.web.ui.webcontrols.dropdownlist?view=netframework-4.8


Phase 1: Research & Reference Setup

Step 1: Add Web Forms Sample Page

Create sample page at samples/BeforeWebForms/ControlSamples/DropDownList/Default.aspx:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="BeforeWebForms.ControlSamples.DropDownList.Default" %>
<!DOCTYPE html>
<html>
<head><title>DropDownList Sample</title></head>
<body>
    <form id="form1" runat="server">
        <h2>Basic DropDownList with Static Items</h2>
        <asp:DropDownList ID="ddlStatic" runat="server">
            <asp:ListItem Text="Select..." Value="" />
            <asp:ListItem Text="Option One" Value="1" />
            <asp:ListItem Text="Option Two" Value="2" />
            <asp:ListItem Text="Option Three" Value="3" />
        </asp:DropDownList>
        
        <h2>With Pre-selected Value</h2>
        <asp:DropDownList ID="ddlSelected" runat="server">
            <asp:ListItem Text="Apple" Value="apple" />
            <asp:ListItem Text="Banana" Value="banana" Selected="True" />
            <asp:ListItem Text="Cherry" Value="cherry" />
        </asp:DropDownList>
        
        <h2>Data-bound DropDownList</h2>
        <asp:DropDownList ID="ddlDataBound" DataTextField="Name" DataValueField="Id" runat="server" />
        
        <h2>Disabled DropDownList</h2>
        <asp:DropDownList ID="ddlDisabled" Enabled="false" runat="server">
            <asp:ListItem Text="Cannot change" Value="1" />
        </asp:DropDownList>
        
        <h2>With CSS Class</h2>
        <asp:DropDownList ID="ddlStyled" CssClass="form-select" runat="server">
            <asp:ListItem Text="Styled" Value="1" />
        </asp:DropDownList>
        
        <h2>With Inline Styles</h2>
        <asp:DropDownList ID="ddlColors" BackColor="LightYellow" ForeColor="Navy" 
                          Width="200px" runat="server">
            <asp:ListItem Text="Colored dropdown" Value="1" />
        </asp:DropDownList>
    </form>
</body>
</html>

Create code-behind Default.aspx.cs:

public partial class Default : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            ddlDataBound.DataSource = new[]
            {
                new { Id = 1, Name = "First Item" },
                new { Id = 2, Name = "Second Item" },
                new { Id = 3, Name = "Third Item" }
            };
            ddlDataBound.DataBind();
        }
    }
}

Step 2: Capture HTML Output

Run the BeforeWebForms project and document the exact HTML output. Expected patterns:

Basic DropDownList:

<select name="ddlStatic" id="ddlStatic">
    <option value="">Select...</option>
    <option value="1">Option One</option>
    <option value="2">Option Two</option>
    <option value="3">Option Three</option>
</select>

With Selected Item:

<select name="ddlSelected" id="ddlSelected">
    <option value="apple">Apple</option>
    <option selected="selected" value="banana">Banana</option>
    <option value="cherry">Cherry</option>
</select>

With CSS Class:

<select name="ddlStyled" id="ddlStyled" class="form-select">
    <option value="1">Styled</option>
</select>

Disabled:

<select name="ddlDisabled" id="ddlDisabled" disabled="disabled">
    <option value="1">Cannot change</option>
</select>

Phase 2: Blazor Implementation

Step 3: Create Supporting Classes

First, create the ListItem class at src/BlazorWebFormsComponents/ListItem.cs:

namespace BlazorWebFormsComponents
{
    public class ListItem
    {
        public string Text { get; set; }
        public string Value { get; set; }
        public bool Selected { get; set; }
        public bool Enabled { get; set; } = true;
        
        public ListItem() { }
        
        public ListItem(string text) : this(text, text) { }
        
        public ListItem(string text, string value)
        {
            Text = text;
            Value = value;
        }
        
        public ListItem(string text, string value, bool selected)
        {
            Text = text;
            Value = value;
            Selected = selected;
        }
    }
}

Create ListItemCollection at src/BlazorWebFormsComponents/ListItemCollection.cs:

namespace BlazorWebFormsComponents
{
    public class ListItemCollection : List<ListItem>
    {
        public...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes FritzAndFriends/BlazorWebFormsComponents#281

<!-- START COPILOT CODING AGENT TIPS -->
---

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more [Copilot coding agent tips](https://gh.io/copilot-coding-agent-tips) in the docs.

Copilot AI and others added 3 commits January 28, 2026 19:15
Co-authored-by: csharpfritz <78577+csharpfritz@users.noreply.github.com>
Co-authored-by: csharpfritz <78577+csharpfritz@users.noreply.github.com>
Co-authored-by: csharpfritz <78577+csharpfritz@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement DropDownList component for Blazor Implement DropDownList component with shared ListItem infrastructure Jan 28, 2026
Copilot AI requested a review from csharpfritz January 28, 2026 19:27
@csharpfritz csharpfritz marked this pull request as ready for review January 28, 2026 20:08
@csharpfritz csharpfritz merged commit 247cb05 into dev Jan 28, 2026
1 check passed
@csharpfritz csharpfritz deleted the copilot/implement-dropdownlist-component branch January 28, 2026 20:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants