# FTRDropDown

## Overview

`FTRDropDown` is a Windows Forms dropdown control designed for single-selection and multi-selection scenarios.

It supports:

* Simple string-based item lists
* Data binding
* Display and value members
* Single selection
* Multi-selection
* Search/filtering
* Keyboard navigation
* Right-to-left (RTL) layouts
* Custom appearance
* Global FTR theme integration
* Optional item descriptions and images through the control's item model
* Premium features protected by the FTR Controls licensing system

**Namespace:** `FTRDropDown`

**Control:** `FTRDropDown`

**Base class:** `FTRControls.BaseClasses.FTRBaseControl`

**Toolbox category:** `FTR Controls`

---

# Installation

Add the FTR Controls assembly to your Windows Forms project and add the control to the Visual Studio Toolbox if required.

After adding the control to the form, it can be configured through the Visual Studio Properties window or programmatically in C#.

Example:

```csharp
using FTRDropDown;

public partial class MainForm : Form
{
    public MainForm()
    {
        InitializeComponent();

        var dropdown = new FTRDropDown
        {
            Location = new Point(20, 20),
            Width = 200
        };

        Controls.Add(dropdown);
    }
}
```

---

# Basic Usage

## Using a String List

The simplest way to populate the control is by using the `Items` property.

```csharp
var ddl = new FTRDropDown();

ddl.Items.AddRange(new[]
{
    "Draft",
    "Published",
    "Archived"
});
```

You can then select an item:

```csharp
ddl.SelectedIndex = 1;
```

The selected item in this example is:

```text
Published
```

---

# Selection

## Single Selection

Single selection is the default mode.

```csharp
var ddl = new FTRDropDown();

ddl.Items.AddRange(new[]
{
    "Small",
    "Medium",
    "Large"
});

ddl.SelectedIndex = 1;
```

The selected item can be retrieved using:

```csharp
string text = ddl.Text;
```

or:

```csharp
string item = ddl.SelectedItem;
```

The zero-based selected index can be retrieved using:

```csharp
int index = ddl.SelectedIndex;
```

If no item is selected, `SelectedIndex` is `-1`.

---

# SelectedItem

`SelectedItem` returns the selected string when the control is populated through the `Items` property.

```csharp
string selected = ddl.SelectedItem;
```

It returns `null` when there is no selected item.

For data-bound controls, use `SelectedValue` or `EditValue` when the underlying value is required.

---

# SelectedValue

`SelectedValue` provides the value associated with the selected item in single-selection mode.

For example, if a data source contains:

```text
Id    Name
1     Draft
2     Published
3     Archived
```

and `ValueMember` is set to `Id`, then:

```csharp
ddl.SelectedValue
```

returns the corresponding `Id`.

Example:

```csharp
ddl.DisplayMember = "Name";
ddl.ValueMember = "Id";
ddl.SelectedValue = 2;
```

The displayed item will be:

```text
Published
```

and:

```csharp
object value = ddl.SelectedValue;
```

returns:

```text
2
```

---

# EditValue

`EditValue` provides the selected backend value.

In single-selection mode, it returns a single value.

In multi-selection mode, it returns a `List<object>` containing the selected values.

### Single Selection

```csharp
object value = ddl.EditValue;
```

### Multi Selection

```csharp
List<object> values = (List<object>)ddl.EditValue;
```

When there is no selection, `EditValue` can be `null` in single-selection mode.

---

# Data Binding

`FTRDropDown` supports data binding through the `DataSource` property.

Supported data-source scenarios include:

* `DataTable`
* `DataView`
* `BindingSource`
* `IEnumerable`
* Lists and collections implementing `IEnumerable`

---

# DataTable Example

Suppose you have the following `DataTable`:

```csharp
DataTable table = new DataTable();

table.Columns.Add("Id", typeof(int));
table.Columns.Add("Name", typeof(string));

table.Rows.Add(1, "Draft");
table.Rows.Add(2, "Published");
table.Rows.Add(3, "Archived");
```

Configure the dropdown as follows:

```csharp
var ddl = new FTRDropDown
{
    DataSource = table,
    DisplayMember = "Name",
    ValueMember = "Id"
};
```

You can then retrieve the selected value:

```csharp
object value = ddl.SelectedValue;
```

---

# Binding a List of Objects

The control can also be bound to a collection of objects.

Example model:

```csharp
public class Status
{
    public int Id { get; set; }
    public string Name { get; set; }
}
```

Create a list:

```csharp
var statuses = new List<Status>
{
    new Status { Id = 1, Name = "Draft" },
    new Status { Id = 2, Name = "Published" },
    new Status { Id = 3, Name = "Archived" }
};
```

Bind it:

```csharp
var ddl = new FTRDropDown
{
    DataSource = statuses,
    DisplayMember = "Name",
    ValueMember = "Id"
};
```

Select an item by value:

```csharp
ddl.SelectedValue = 2;
```

Retrieve the selected value:

```csharp
object value = ddl.SelectedValue;
```

---

# DisplayMember

`DisplayMember` specifies the property or column displayed to the user.

Example:

```csharp
ddl.DisplayMember = "Name";
```

For a `DataTable`, this corresponds to a column name.

For an object collection, this corresponds to a public property.

If `DisplayMember` is not specified, the control uses the first available column for a `DataTable` or the object's `ToString()` representation for object collections.

---

# ValueMember

`ValueMember` specifies the property or column used as the underlying value.

Example:

```csharp
ddl.ValueMember = "Id";
```

This allows the displayed text and the actual selected value to be different.

For example:

```text
Displayed text: Published
Selected value: 2
```

---

# Multi-Select

`MultiSelect` enables multiple item selection.

> **Premium Feature:** `MultiSelect` requires a valid FTR Controls license.

Enable it:

```csharp
ddl.MultiSelect = true;
```

Example:

```csharp
var ddl = new FTRDropDown
{
    MultiSelect = true
};

ddl.Items.AddRange(new[]
{
    "C#",
    "SQL Server",
    "JavaScript",
    "HTML",
    "CSS"
});
```

Multiple items can then be selected by the user.

---

# Reading Multi-Select Values

In multi-select mode, use `EditValue` to retrieve the selected values.

```csharp
var values = ddl.EditValue as List<object>;
```

Example:

```csharp
if (ddl.EditValue is List<object> values)
{
    foreach (var value in values)
    {
        Console.WriteLine(value);
    }
}
```

The values are returned in the order of the items in the dropdown.

---

# Setting Multi-Select Values

You can assign multiple values through `EditValue`.

```csharp
ddl.EditValue = new List<object>
{
    1,
    3
};
```

When `ValueMember` is configured, the values are matched against the corresponding data-source values.

For simple string lists, values can be assigned directly:

```csharp
ddl.EditValue = new List<object>
{
    "C#",
    "SQL Server"
};
```

---

# SelectedItemsChanged

`SelectedItemsChanged` is raised when the checked items change in multi-select mode.

Example:

```csharp
ddl.SelectedItemsChanged += (sender, e) =>
{
    if (ddl.EditValue is List<object> values)
    {
        Console.WriteLine($"Selected items: {values.Count}");
    }
};
```

This event is the recommended event for reacting to multi-selection changes.

---

# SelectedIndexChanged

`SelectedIndexChanged` is raised when the selected index changes in single-selection mode.

Example:

```csharp
ddl.SelectedIndexChanged += (sender, e) =>
{
    Console.WriteLine($"Selected: {ddl.Text}");
};
```

For multi-select scenarios, use `SelectedItemsChanged` instead.

---

# Search Box

The dropdown supports an integrated search box for filtering items.

> **Premium Feature:** `ShowSearchBox` requires a valid FTR Controls license when enabled.

Example:

```csharp
ddl.ShowSearchBox = true;
```

The search box filters items while the user types.

The search operation checks both:

* Item text
* Item description

---

# SearchBoxPlaceholder

`SearchBoxPlaceholder` specifies the text displayed when the search box is empty.

Default value:

```text
Search...
```

Example:

```csharp
ddl.SearchBoxPlaceholder = "Search status...";
```

---

# SearchBoxHeight

`SearchBoxHeight` controls the height of the search box.

Example:

```csharp
ddl.SearchBoxHeight = 40;
```

The minimum supported value is 20 pixels.

---

# Search Box Appearance

The search box provides several appearance properties:

### SearchBoxBackColor

Controls the search box background color.

```csharp
ddl.SearchBoxBackColor = Color.White;
```

### SearchBoxForeColor

Controls the search text color.

```csharp
ddl.SearchBoxForeColor = Color.Black;
```

### SearchBoxPlaceholderColor

Controls the placeholder text color.

```csharp
ddl.SearchBoxPlaceholderColor = Color.Gray;
```

### SearchBoxBorderColor

Controls the search box border color.

```csharp
ddl.SearchBoxBorderColor = Color.LightGray;
```

### SearchBoxBorderRadius

Controls the search box corner radius.

```csharp
ddl.SearchBoxBorderRadius = 6;
```

### SearchBoxBorderWidth

Controls the search box border width.

```csharp
ddl.SearchBoxBorderWidth = 1;
```

---

# Appearance

## BorderColor

Controls the outer border color.

```csharp
ddl.BorderColor = Color.Gray;
```

## BorderWidth

Controls the outer border width.

```csharp
ddl.BorderWidth = 1.5f;
```

The minimum supported border width is 0.5.

## InnerBackColor

Controls the main background of the dropdown.

```csharp
ddl.InnerBackColor = Color.White;
```

The control's `BackColor` is transparent by default. `InnerBackColor` is the property normally used to control the visible background.

## HoverBackColor

Controls the background color of the item currently under the mouse pointer.

```csharp
ddl.HoverBackColor = Color.LightBlue;
```

---

# BorderRadius

`BorderRadius` controls the rounded corners of the dropdown.

> **Premium Feature:** `BorderRadius` requires a valid FTR Controls license.

Example:

```csharp
ddl.BorderRadius = 10;
```

A value of `0` produces square corners.

---

# MaxDropHeight

`MaxDropHeight` defines the maximum height of the dropdown popup.

Example:

```csharp
ddl.MaxDropHeight = 400;
```

If the content is larger than the maximum height, the popup provides scrolling.

---

# Text

`Text` represents the currently displayed selection.

In single-selection mode:

```csharp
string text = ddl.Text;
```

You can also assign text to select an item:

```csharp
ddl.Text = "Published";
```

The control first attempts an exact case-insensitive match. If no exact match is found, it attempts a partial match.

In multi-select mode, `Text` displays a summary of the selected items.

For example:

```text
C#, SQL Server
```

If more than two items are selected, the control displays a summary similar to:

```text
C#, SQL Server and 3 others
```

---

# Keyboard Navigation

The control supports keyboard navigation.

### Down Arrow

When the dropdown is closed, pressing `Down` opens it.

When the popup is open, `Down` moves the keyboard selection downward.

### Up Arrow

Moves the keyboard selection upward.

### Enter

Selects the currently highlighted item.

In multi-select mode, Enter toggles the checked state of the highlighted item.

### Escape

Closes the dropdown popup without selecting another item.

---

# Right-to-Left (RTL) Support

The control supports right-to-left layouts.

Example:

```csharp
ddl.RightToLeft = RightToLeft.Yes;
```

RTL affects the layout of the control, popup content, search box, text alignment, checkbox positioning, and dropdown arrow.

The control also detects common RTL text automatically when rendering item text.

---

# Themes

`FTRDropDown` integrates with the FTR Controls theme system.

The control supports the global FTR theme configuration and updates its appearance when the active theme changes.

The control exposes:

```csharp
ddl.ApplyTheme();
```

Use `ApplyTheme()` when you need to explicitly reapply the current FTR theme.

Custom appearance properties can also be used when an application requires a specific appearance.

---

# DropDownItem

`DropDownItem` is the item model used internally by the dropdown to represent an item.

It provides the following public properties:

| Property      | Type     | Description                              |
| ------------- | -------- | ---------------------------------------- |
| `Text`        | `string` | Display text                             |
| `Description` | `string` | Optional item description                |
| `Image`       | `Image`  | Optional item image                      |
| `Tag`         | `object` | Optional custom data                     |
| `Checked`     | `bool`   | Checked state for multi-select scenarios |
| `Index`       | `int`    | Item index                               |
| `Height`      | `int`    | Item height                              |

The control's public high-level data-binding API is based on `Items` and `DataSource`. The current `FTRDropDown` API does not expose a public `DropDownItem` collection for directly adding custom `DropDownItem` instances.

Therefore, applications should normally populate the control using `Items` or `DataSource`.

---

# Properties Reference

| Property                    | Type           |       Default | Premium | Description                                     |
| --------------------------- | -------------- | ------------: | :-----: | ----------------------------------------------- |
| `Items`                     | `List<string>` |         Empty |    No   | Simple string-based item list                   |
| `Text`                      | `string`       |         Empty |    No   | Current displayed selection                     |
| `SelectedIndex`             | `int`          |          `-1` |    No   | Selected item index in single-select mode       |
| `SelectedItem`              | `string`       |        `null` |    No   | Selected string item                            |
| `SelectedValue`             | `object`       |        `null` |    No   | Selected data-bound value in single-select mode |
| `EditValue`                 | `object`       |        `null` |    No   | Selected value or values                        |
| `DataSource`                | `object`       |        `null` |    No   | Data source                                     |
| `DisplayMember`             | `string`       |         Empty |    No   | Display property/column                         |
| `ValueMember`               | `string`       |         Empty |    No   | Value property/column                           |
| `BorderColor`               | `Color`        |   Theme-based |    No   | Outer border color                              |
| `BorderWidth`               | `float`        |           `1` |    No   | Outer border width                              |
| `InnerBackColor`            | `Color`        |   Theme-based |    No   | Main dropdown background                        |
| `ForeColor`                 | `Color`        |   Theme-based |    No   | Main text color                                 |
| `HoverBackColor`            | `Color`        |   Theme-based |    No   | Item hover background                           |
| `MaxDropHeight`             | `int`          |         `400` |    No   | Maximum popup height                            |
| `ShowSearchBox`             | `bool`         |        `true` | **Yes** | Enables the search box                          |
| `SearchBoxHeight`           | `int`          |          `36` |    No   | Search box height                               |
| `SearchBoxPlaceholder`      | `string`       | `"Search..."` |    No   | Search placeholder                              |
| `SearchBoxBackColor`        | `Color`        |   Theme-based |    No   | Search background                               |
| `SearchBoxForeColor`        | `Color`        |   Theme-based |    No   | Search text color                               |
| `SearchBoxPlaceholderColor` | `Color`        |   Theme-based |    No   | Placeholder color                               |
| `SearchBoxBorderColor`      | `Color`        |   Theme-based |    No   | Search border color                             |
| `SearchBoxBorderRadius`     | `int`          |           `6` |    No   | Search corner radius                            |
| `SearchBoxBorderWidth`      | `float`        |           `1` |    No   | Search border width                             |
| `BorderRadius`              | `int`          |           `8` | **Yes** | Dropdown corner radius                          |
| `MultiSelect`               | `bool`         |       `false` | **Yes** | Enables multiple selection                      |

---

# Events Reference

| Event                  | Description                                                    |
| ---------------------- | -------------------------------------------------------------- |
| `SelectedIndexChanged` | Occurs when the selected index changes                         |
| `SelectedItemsChanged` | Occurs when selected/checked items change in multi-select mode |

---

# Methods Reference

| Method         | Description                                            |
| -------------- | ------------------------------------------------------ |
| `ApplyTheme()` | Applies the current FTR Controls theme to the dropdown |

---

# Common Examples

## Simple Dropdown

```csharp
var ddl = new FTRDropDown();

ddl.Items.AddRange(new[]
{
    "Draft",
    "Published",
    "Archived"
});

ddl.SelectedIndexChanged += (sender, e) =>
{
    statusLabel.Text = ddl.Text;
};
```

---

## Searchable Dropdown

```csharp
var ddl = new FTRDropDown
{
    ShowSearchBox = true,
    SearchBoxPlaceholder = "Search status..."
};

ddl.Items.AddRange(new[]
{
    "Draft",
    "Published",
    "Archived",
    "Pending",
    "Rejected"
});
```

---

## Data-Bound Dropdown

```csharp
var ddl = new FTRDropDown
{
    DataSource = statuses,
    DisplayMember = "Name",
    ValueMember = "Id"
};

ddl.SelectedValue = 2;
```

---

## Multi-Select Dropdown

```csharp
var ddl = new FTRDropDown
{
    MultiSelect = true
};

ddl.Items.AddRange(new[]
{
    "C#",
    "SQL Server",
    "JavaScript",
    "HTML",
    "CSS"
});

ddl.SelectedItemsChanged += (sender, e) =>
{
    var selected = ddl.EditValue as List<object>;

    if (selected != null)
    {
        Console.WriteLine($"Selected: {selected.Count}");
    }
};
```

---

# Licensing

FTRDropDown contains premium functionality protected by the FTR Controls licensing system.

The following features require a valid FTR Controls license:

* `BorderRadius`
* `MultiSelect`
* `ShowSearchBox`

When a premium property is enabled without a valid license, the control displays the FTR Controls activation prompt and does not apply the requested premium setting.

All other documented features are available without activating these premium features.

For licensing, activation, and license management instructions, refer to the main FTR Controls licensing documentation supplied with the product.

---

# Recommended Usage

For most applications:

### Simple list

Use:

```csharp
Items
```

### Database or object collection

Use:

```csharp
DataSource
DisplayMember
ValueMember
```

### Single selection

Use:

```csharp
SelectedIndex
SelectedItem
SelectedValue
EditValue
```

### Multiple selection

Use:

```csharp
MultiSelect = true
EditValue
SelectedItemsChanged
```

### Search

Use:

```csharp
ShowSearchBox = true
SearchBoxPlaceholder
```

### Custom appearance

Use:

```csharp
BorderColor
BorderWidth
InnerBackColor
ForeColor
HoverBackColor
```

---

# Important Notes

* `SelectedIndex` is meaningful for single-selection mode. In multi-select mode, use `EditValue` to retrieve the selected values.
* `SelectedValue` is intended for single-selection scenarios.
* `EditValue` returns a single value in single-select mode and a `List<object>` in multi-select mode.
* `DisplayMember` and `ValueMember` are especially useful when binding to objects, `DataTable`, `DataView`, or other supported collections.
* `ShowSearchBox`, `MultiSelect`, and `BorderRadius` are premium features.
* The search box filters both item text and item descriptions.
* `BackColor` is transparent by default; use `InnerBackColor` when you need to control the visible dropdown background.
* For multi-selection change notifications, use `SelectedItemsChanged`.
* The current public API does not provide a direct `DropDownItem` collection for manually adding rich items. Use `Items` or `DataSource` for normal application usage.

---

# API Summary

### Namespace

```csharp
FTRDropDown
```

### Main Control

```csharp
FTRDropDown
```

### Item Model

```csharp
DropDownItem
```

### Main Selection APIs

```csharp
SelectedIndex
SelectedItem
SelectedValue
EditValue
```

### Data Binding APIs

```csharp
DataSource
DisplayMember
ValueMember
```

### Selection Events

```csharp
SelectedIndexChanged
SelectedItemsChanged
```

### Appearance APIs

```csharp
BorderColor
BorderWidth
InnerBackColor
ForeColor
HoverBackColor
BorderRadius
```

### Search APIs

```csharp
ShowSearchBox
SearchBoxHeight
SearchBoxPlaceholder
SearchBoxBackColor
SearchBoxForeColor
SearchBoxPlaceholderColor
SearchBoxBorderColor
SearchBoxBorderRadius
SearchBoxBorderWidth
```

### Other

```csharp
MaxDropHeight
ApplyTheme()
```
