BeepDropDownMenu
Advanced dropdown menu control with smooth animations and customizable item lists for modern selection interfaces
?? Table of Contents
Overview
BeepDropDownMenu provides an advanced dropdown menu control that extends BeepListBox functionality with smooth animations, intelligent sizing, and integrated dropdown button management. It offers a modern alternative to traditional ComboBox controls with enhanced customization, theming support, and visual appeal.
Built on the BeepListBox foundation, BeepDropDownMenu features animated expand/collapse behavior, intelligent height management, customizable appearance, hit area detection, and comprehensive theme integration. Perfect for selection interfaces, menu systems, filter controls, and any scenario requiring elegant dropdown functionality.
Key Features
?? Smooth Animations
Fluid expand/collapse animations with configurable speed and timing
?? Integrated Button
Built-in dropdown button with automatic icon switching and theme integration
?? Smart Sizing
Intelligent height calculation with maximum height constraints and content adaptation
??? Hit Area Detection
Precise click detection for dropdown button with custom hit area management
?? BeepListBox Heritage
Full BeepListBox functionality including icons, custom items, and selection handling
? Performance Optimized
Efficient animation system with minimal resource usage and smooth operation
Visual Preview
Dropdown States
Collapsed State
Compact collapsed state showing selected value or placeholder
Expanded State
Expanded state showing animated item list with selection highlighting
BeepDropDownMenu showing collapsed and expanded states with smooth transitions
Filter Dropdown Example
Filter interface using multiple BeepDropDownMenu controls for data filtering
Basic Usage
Simple Dropdown Menu
// Create a BeepDropDownMenu
var dropdownMenu = new BeepDropDownMenu();
dropdownMenu.Size = new Size(200, 30);
dropdownMenu.Location = new Point(50, 50);
// Add menu items
dropdownMenu.ListItems.Add(new SimpleItem
{
Text = "Option 1",
ImagePath = "option1-icon.svg",
GuidId = Guid.NewGuid().ToString()
});
dropdownMenu.ListItems.Add(new SimpleItem
{
Text = "Option 2",
ImagePath = "option2-icon.svg",
GuidId = Guid.NewGuid().ToString()
});
dropdownMenu.ListItems.Add(new SimpleItem
{
Text = "Option 3",
ImagePath = "option3-icon.svg",
GuidId = Guid.NewGuid().ToString()
});
// Handle selection changes
dropdownMenu.SelectedItemChanged += (sender, e) =>
{
if (dropdownMenu.SelectedItem != null)
{
// Console.WriteLine($"Selected: {dropdownMenu.SelectedItem.Text}");
}
};
// Add to form
this.Controls.Add(dropdownMenu);
Category Filter Dropdown
public void SetupCategoryFilter()
{
var categoryFilter = new BeepDropDownMenu
{
Size = new Size(180, 30),
Location = new Point(20, 20),
Text = "Filter by Category"
};
// Add category options
var categories = new[]
{
new { Name = "All Categories", Icon = "all-icon.svg", Value = "" },
new { Name = "Software Development", Icon = "dev-icon.svg", Value = "software" },
new { Name = "Design & UI/UX", Icon = "design-icon.svg", Value = "design" },
new { Name = "Data Science", Icon = "data-icon.svg", Value = "data" },
new { Name = "Project Management", Icon = "project-icon.svg", Value = "management" },
new { Name = "Marketing", Icon = "marketing-icon.svg", Value = "marketing" }
};
foreach (var category in categories)
{
categoryFilter.ListItems.Add(new SimpleItem
{
Text = category.Name,
ImagePath = category.Icon,
Tag = category.Value,
GuidId = Guid.NewGuid().ToString()
});
}
// Handle category selection
categoryFilter.SelectedItemChanged += (sender, e) =>
{
if (categoryFilter.SelectedItem != null)
{
var selectedCategory = categoryFilter.SelectedItem.Tag?.ToString();
ApplyCategoryFilter(selectedCategory);
}
};
// Set default selection
categoryFilter.SelectedIndex = 0;
this.Controls.Add(categoryFilter);
}
private void ApplyCategoryFilter(string category)
{
// Apply filter to data grid or list
if (string.IsNullOrEmpty(category))
{
ShowAllItems();
}
else
{
FilterItemsByCategory(category);
}
}
Multi-Level Dropdown Configuration
public class DropdownConfiguration
{
public string Title { get; set; }
public Size Size { get; set; }
public Point Location { get; set; }
public List Items { get; set; } = new List();
public bool ShowIcons { get; set; } = true;
public int MaxHeight { get; set; } = 200;
}
public class DropdownItem
{
public string Text { get; set; }
public string IconPath { get; set; }
public object Value { get; set; }
public bool IsEnabled { get; set; } = true;
}
public BeepDropDownMenu CreateConfiguredDropdown(DropdownConfiguration config)
{
var dropdown = new BeepDropDownMenu
{
Size = config.Size,
Location = config.Location,
Text = config.Title
};
// Configure maximum height
if (config.MaxHeight > 0)
{
dropdown.MaxMenuHeight = config.MaxHeight;
}
// Add items from configuration
foreach (var item in config.Items)
{
var simpleItem = new SimpleItem
{
Text = item.Text,
ImagePath = config.ShowIcons ? item.IconPath : null,
Tag = item.Value,
Enabled = item.IsEnabled,
GuidId = Guid.NewGuid().ToString()
};
dropdown.ListItems.Add(simpleItem);
}
return dropdown;
}
// Usage example
public void SetupApplicationFilters()
{
// Priority filter
var priorityConfig = new DropdownConfiguration
{
Title = "Priority",
Size = new Size(120, 30),
Location = new Point(20, 60),
Items = new List
{
new DropdownItem { Text = "All", IconPath = "all.svg", Value = null },
new DropdownItem { Text = "High", IconPath = "high.svg", Value = "high" },
new DropdownItem { Text = "Medium", IconPath = "medium.svg", Value = "medium" },
new DropdownItem { Text = "Low", IconPath = "low.svg", Value = "low" }
}
};
var priorityDropdown = CreateConfiguredDropdown(priorityConfig);
priorityDropdown.SelectedItemChanged += (s, e) => FilterByPriority(priorityDropdown.SelectedItem?.Tag?.ToString());
// Status filter
var statusConfig = new DropdownConfiguration
{
Title = "Status",
Size = new Size(140, 30),
Location = new Point(150, 60),
Items = new List
{
new DropdownItem { Text = "All Statuses", IconPath = "all.svg", Value = null },
new DropdownItem { Text = "Active", IconPath = "active.svg", Value = "active" },
new DropdownItem { Text = "Pending", IconPath = "pending.svg", Value = "pending" },
new DropdownItem { Text = "Completed", IconPath = "completed.svg", Value = "completed" },
new DropdownItem { Text = "Cancelled", IconPath = "cancelled.svg", Value = "cancelled" }
}
};
var statusDropdown = CreateConfiguredDropdown(statusConfig);
statusDropdown.SelectedItemChanged += (s, e) => FilterByStatus(statusDropdown.SelectedItem?.Tag?.ToString());
// Add to form
this.Controls.Add(priorityDropdown);
this.Controls.Add(statusDropdown);
}
private void FilterByPriority(string priority) { /* Implementation */ }
private void FilterByStatus(string status) { /* Implementation */ }
Properties
Dropdown-Specific Properties
| Property | Type | Default | Description |
|---|---|---|---|
IsExpanded |
bool | false | Whether the dropdown menu is currently expanded |
MaxMenuHeight |
int | 200 | Maximum height of the dropdown when expanded |
CollapsedHeight |
int | 30 | Height of the dropdown when collapsed |
ButtonWidth |
int | 25 | Width of the dropdown button |
Animation Properties
| Property | Type | Default | Description |
|---|---|---|---|
AnimationInterval |
const int | 15 | Animation timer interval in milliseconds |
HeightIncrement |
const int | 10 | Height change per animation step |
IsAnimating |
bool | false | Whether animation is currently in progress |
Inherited from BeepListBox
| Property | Type | Description |
|---|---|---|
ListItems |
BindingList<SimpleItem> | Collection of dropdown menu items |
SelectedIndex |
int | Index of currently selected item |
SelectedItem |
SimpleItem | Currently selected menu item |
ShowCheckBox |
bool | Whether to show checkboxes for items |
Button Properties
| Property | Type | Description |
|---|---|---|
DropDownButtonGDI |
BeepButton | Internal button used for dropdown rendering |
Events
Inherited from BeepListBox
| Event | Event Args | Description |
|---|---|---|
SelectedItemChanged |
EventHandler | Fired when the selected item changes |
ListItemClicked |
Override method | Handles individual item clicks from list items |
Standard Control Events
| Event | Description |
|---|---|
Click |
General click events on the control |
MouseEnter |
Mouse entering the control area |
MouseLeave |
Mouse leaving the control area |
Resize |
Control size changes |
Examples
Settings Configuration Panel
public class SettingsPanel : Panel
{
private BeepDropDownMenu themeSelector;
private BeepDropDownMenu languageSelector;
private BeepDropDownMenu fontSizeSelector;
private BeepDropDownMenu layoutSelector;
public SettingsPanel()
{
SetupSettingsControls();
ApplyLayout();
}
private void SetupSettingsControls()
{
// Theme selector
themeSelector = new BeepDropDownMenu
{
Size = new Size(150, 30),
Text = "Select Theme"
};
var themes = new[]
{
new { Name = "Light Theme", Value = "Light", Icon = "sun.svg" },
new { Name = "Dark Theme", Value = "Dark", Icon = "moon.svg" },
new { Name = "Auto (System)", Value = "Auto", Icon = "auto.svg" },
new { Name = "High Contrast", Value = "HighContrast", Icon = "contrast.svg" }
};
foreach (var theme in themes)
{
themeSelector.ListItems.Add(new SimpleItem
{
Text = theme.Name,
ImagePath = theme.Icon,
Tag = theme.Value,
GuidId = Guid.NewGuid().ToString()
});
}
themeSelector.SelectedItemChanged += (s, e) =>
{
if (themeSelector.SelectedItem?.Tag is string selectedTheme)
{
ApplyTheme(selectedTheme);
}
};
// Language selector
languageSelector = new BeepDropDownMenu
{
Size = new Size(120, 30),
Text = "Language"
};
var languages = new[]
{
new { Name = "English", Code = "en", Flag = "flag-us.svg" },
new { Name = "Spanish", Code = "es", Flag = "flag-es.svg" },
new { Name = "French", Code = "fr", Flag = "flag-fr.svg" },
new { Name = "German", Code = "de", Flag = "flag-de.svg" },
new { Name = "Chinese", Code = "zh", Flag = "flag-cn.svg" }
};
foreach (var lang in languages)
{
languageSelector.ListItems.Add(new SimpleItem
{
Text = lang.Name,
ImagePath = lang.Flag,
Tag = lang.Code,
GuidId = Guid.NewGuid().ToString()
});
}
languageSelector.SelectedItemChanged += (s, e) =>
{
if (languageSelector.SelectedItem?.Tag is string langCode)
{
ChangeLanguage(langCode);
}
};
// Font size selector
fontSizeSelector = new BeepDropDownMenu
{
Size = new Size(100, 30),
Text = "Font Size"
};
var fontSizes = new[] { 8, 9, 10, 11, 12, 14, 16, 18, 20, 24 };
foreach (var size in fontSizes)
{
fontSizeSelector.ListItems.Add(new SimpleItem
{
Text = $"{size}pt",
Tag = size,
GuidId = Guid.NewGuid().ToString()
});
}
fontSizeSelector.SelectedItemChanged += (s, e) =>
{
if (fontSizeSelector.SelectedItem?.Tag is int fontSize)
{
ChangeFontSize(fontSize);
}
};
// Layout selector
layoutSelector = new BeepDropDownMenu
{
Size = new Size(140, 30),
Text = "Layout"
};
var layouts = new[]
{
new { Name = "Standard", Value = "standard", Icon = "layout-standard.svg" },
new { Name = "Compact", Value = "compact", Icon = "layout-compact.svg" },
new { Name = "Wide", Value = "wide", Icon = "layout-wide.svg" },
new { Name = "Sidebar", Value = "sidebar", Icon = "layout-sidebar.svg" }
};
foreach (var layout in layouts)
{
layoutSelector.ListItems.Add(new SimpleItem
{
Text = layout.Name,
ImagePath = layout.Icon,
Tag = layout.Value,
GuidId = Guid.NewGuid().ToString()
});
}
layoutSelector.SelectedItemChanged += (s, e) =>
{
if (layoutSelector.SelectedItem?.Tag is string layoutType)
{
ChangeLayout(layoutType);
}
};
// Add controls to panel
this.Controls.AddRange(new Control[]
{
themeSelector, languageSelector, fontSizeSelector, layoutSelector
});
}
private void ApplyLayout()
{
var startY = 20;
var spacing = 60;
var labelOffset = -20;
// Theme selector
var themeLabel = new Label { Text = "Theme:", Size = new Size(60, 20), Location = new Point(20, startY + labelOffset) };
themeSelector.Location = new Point(20, startY);
this.Controls.Add(themeLabel);
// Language selector
var langLabel = new Label { Text = "Language:", Size = new Size(70, 20), Location = new Point(190, startY + labelOffset) };
languageSelector.Location = new Point(190, startY);
this.Controls.Add(langLabel);
// Font size selector
var fontLabel = new Label { Text = "Font Size:", Size = new Size(70, 20), Location = new Point(330, startY + labelOffset) };
fontSizeSelector.Location = new Point(330, startY);
this.Controls.Add(fontLabel);
// Layout selector
var layoutLabel = new Label { Text = "Layout:", Size = new Size(60, 20), Location = new Point(20, startY + spacing + labelOffset) };
layoutSelector.Location = new Point(20, startY + spacing);
this.Controls.Add(layoutLabel);
}
private void ApplyTheme(string theme)
{
// Apply selected theme to application
Properties.Settings.Default.Theme = theme;
Properties.Settings.Default.Save();
// Notify application of theme change
Application.Restart();
}
private void ChangeLanguage(string languageCode)
{
// Change application language
Properties.Settings.Default.Language = languageCode;
Properties.Settings.Default.Save();
// Update UI text
UpdateUILanguage(languageCode);
}
private void ChangeFontSize(int fontSize)
{
// Apply font size change
Properties.Settings.Default.FontSize = fontSize;
Properties.Settings.Default.Save();
// Update application fonts
UpdateApplicationFonts(fontSize);
}
private void ChangeLayout(string layoutType)
{
// Apply layout change
Properties.Settings.Default.Layout = layoutType;
Properties.Settings.Default.Save();
// Update application layout
UpdateApplicationLayout(layoutType);
}
// Helper methods
private void UpdateUILanguage(string languageCode) { /* Implementation */ }
private void UpdateApplicationFonts(int fontSize) { /* Implementation */ }
private void UpdateApplicationLayout(string layoutType) { /* Implementation */ }
}
Theming
BeepDropDownMenu inherits comprehensive theming from BeepListBox with additional dropdown-specific styling:
Theme Application
var dropdown = new BeepDropDownMenu
{
Theme = "DarkTheme",
Size = new Size(200, 30)
};
// Theme automatically applies to:
// - Dropdown background and borders
// - Item list styling
// - Dropdown button appearance
// - Animation transitions
// - Hover and selection states
// Manual theme refresh
dropdown.ApplyTheme();
Dropdown Theming Properties
- PanelBackColor - Dropdown background color
- ButtonBackColor - Dropdown button background
- ButtonForeColor - Button icon color
- ButtonHoverBackColor - Button hover state
- ListBackColor - Item list background
- ListItemBackColor - Individual item backgrounds
- ListItemHoverBackColor - Item hover states
- BorderColor - Control borders and dividers
Best Practices
?? Visual Design
- Consistent sizing: Use consistent heights for dropdown controls across your application
- Clear labeling: Provide clear labels or placeholder text for dropdown purpose
- Icon usage: Use icons consistently to improve visual recognition
- Animation speed: Keep animations fast enough to feel responsive but smooth
?? Data Management
- Logical ordering: Order items logically (alphabetical, frequency, importance)
- Default selection: Set meaningful default selections when appropriate
- Dynamic updates: Update dropdown contents based on context changes
- State persistence: Remember user selections where appropriate
? Performance
- Efficient animation: Use timer-based animations sparingly and efficiently
- Lazy loading: Load dropdown items only when needed for large datasets
- Memory management: Dispose of animation timers properly
- Update optimization: Minimize unnecessary UI updates during animations
?? Implementation
- Event handling: Handle selection changes appropriately without performance issues
- Validation: Validate selections and provide feedback for invalid states
- Accessibility: Support keyboard navigation and screen readers
- Error handling: Handle edge cases like empty item lists gracefully
Adjust animation speed based on the number of items - shorter lists can animate faster, while longer lists benefit from slightly slower animations for better visual tracking.
Always provide a meaningful default selection or clear placeholder text to guide users on the dropdown's purpose and expected interaction.
Be mindful of animation timer disposal - ensure timers are properly stopped and disposed to prevent memory leaks in long-running applications.