|
@@ -1,22 +1,3 @@
|
|
|
-//
|
|
|
-// ListView.cs: ListView control
|
|
|
-//
|
|
|
-// Authors:
|
|
|
-// Miguel de Icaza ([email protected])
|
|
|
-//
|
|
|
-//
|
|
|
-// TODO:
|
|
|
-// - Should we support multiple columns, if so, how should that be done?
|
|
|
-// - Show mark for items that have been marked.
|
|
|
-// - Mouse support
|
|
|
-// - Scrollbars?
|
|
|
-//
|
|
|
-// Column considerations:
|
|
|
-// - Would need a way to specify widths
|
|
|
-// - Should it automatically extract data out of structs/classes based on public fields/properties?
|
|
|
-// - It seems that this would be useful just for the "simple" API, not the IListDAtaSource, as that one has full support for it.
|
|
|
-// - Should a function be specified that retrieves the individual elements?
|
|
|
-//
|
|
|
using System;
|
|
|
using System.Collections;
|
|
|
using System.Collections.Generic;
|
|
@@ -59,7 +40,7 @@ namespace Terminal.Gui {
|
|
|
/// <summary>
|
|
|
/// Should return whether the specified item is currently marked.
|
|
|
/// </summary>
|
|
|
- /// <returns><c>true</c>, if marked, <c>false</c> otherwise.</returns>
|
|
|
+ /// <returns><see langword="true"/>, if marked, <see langword="false"/> otherwise.</returns>
|
|
|
/// <param name="item">Item index.</param>
|
|
|
bool IsMarked (int item);
|
|
|
|
|
@@ -67,7 +48,7 @@ namespace Terminal.Gui {
|
|
|
/// Flags the item as marked.
|
|
|
/// </summary>
|
|
|
/// <param name="item">Item index.</param>
|
|
|
- /// <param name="value">If set to <c>true</c> value.</param>
|
|
|
+ /// <param name="value">If set to <see langword="true"/> value.</param>
|
|
|
void SetMark (int item, bool value);
|
|
|
|
|
|
/// <summary>
|
|
@@ -77,6 +58,21 @@ namespace Terminal.Gui {
|
|
|
IList ToList ();
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Implement <see cref="IListDataSourceSearchable"/> to provide custom rendering for a <see cref="ListView"/> that
|
|
|
+ /// supports searching for items.
|
|
|
+ /// </summary>
|
|
|
+ public interface IListDataSourceSearchable : IListDataSource {
|
|
|
+ /// <summary>
|
|
|
+ /// Finds the first item that starts with the specified search string. Used by the default implementation
|
|
|
+ /// to support typing the first characters of an item to find it and move the selection to i.
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="search">Text to search for.</param>
|
|
|
+ /// <returns>The index of the first <see cref="ListView"/> item that starts with <paramref name="search"/>.
|
|
|
+ /// Returns <see langword="-1"/> if <paramref name="search"/> was not found.</returns>
|
|
|
+ int StartsWith (string search);
|
|
|
+ }
|
|
|
+
|
|
|
/// <summary>
|
|
|
/// ListView <see cref="View"/> renders a scrollable list of data where each item can be activated to perform an action.
|
|
|
/// </summary>
|
|
@@ -89,8 +85,8 @@ namespace Terminal.Gui {
|
|
|
/// <para>
|
|
|
/// By default <see cref="ListView"/> uses <see cref="object.ToString"/> to render the items of any
|
|
|
/// <see cref="IList"/> object (e.g. arrays, <see cref="List{T}"/>,
|
|
|
- /// and other collections). Alternatively, an object that implements the <see cref="IListDataSource"/>
|
|
|
- /// interface can be provided giving full control of what is rendered.
|
|
|
+ /// and other collections). Alternatively, an object that implements <see cref="IListDataSource"/>
|
|
|
+ /// or <see cref="IListDataSourceSearchable"/> can be provided giving full control of what is rendered.
|
|
|
/// </para>
|
|
|
/// <para>
|
|
|
/// <see cref="ListView"/> can display any object that implements the <see cref="IList"/> interface.
|
|
@@ -107,6 +103,11 @@ namespace Terminal.Gui {
|
|
|
/// [x] or [ ] and bind the SPACE key to toggle the selection. To implement a different
|
|
|
/// marking style set <see cref="AllowsMarking"/> to false and implement custom rendering.
|
|
|
/// </para>
|
|
|
+ /// <para>
|
|
|
+ /// By default or if <see cref="Source"/> is set to an object that implements
|
|
|
+ /// <see cref="IListDataSourceSearchable"/>, searching the ListView with the keyboard is supported. Users type the
|
|
|
+ /// first characters of an item, and the first item that starts with what the user types will be selected.
|
|
|
+ /// </para>
|
|
|
/// </remarks>
|
|
|
public class ListView : View {
|
|
|
int top, left;
|
|
@@ -169,11 +170,10 @@ namespace Terminal.Gui {
|
|
|
/// <summary>
|
|
|
/// Gets or sets whether this <see cref="ListView"/> allows items to be marked.
|
|
|
/// </summary>
|
|
|
- /// <value><c>true</c> if allows marking elements of the list; otherwise, <c>false</c>.
|
|
|
- /// </value>
|
|
|
+ /// <value>Set to <see langword="true"/> to allow marking elements of the list.</value>
|
|
|
/// <remarks>
|
|
|
- /// If set to true, <see cref="ListView"/> will render items marked items with "[x]", and unmarked items with "[ ]"
|
|
|
- /// spaces. SPACE key will toggle marking.
|
|
|
+ /// If set to <see langword="true"/>, <see cref="ListView"/> will render items marked items with "[x]", and unmarked items with "[ ]"
|
|
|
+ /// spaces. SPACE key will toggle marking. The default is <see langword="false"/>.
|
|
|
/// </remarks>
|
|
|
public bool AllowsMarking {
|
|
|
get => allowsMarking;
|
|
@@ -184,7 +184,8 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// If set to true allows more than one item to be selected. If false only allow one item selected.
|
|
|
+ /// If set to <see langword="true"/> more than one item can be selected. If <see langword="false"/> selecting
|
|
|
+ /// an item will cause all others to be un-selected. The default is <see langword="false"/>.
|
|
|
/// </summary>
|
|
|
public bool AllowsMultipleSelection {
|
|
|
get => allowsMultipleSelection;
|
|
@@ -219,7 +220,7 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Gets or sets the left column where the item start to be displayed at on the <see cref="ListView"/>.
|
|
|
+ /// Gets or sets the leftmost column that is currently visible (when scrolling horizontally).
|
|
|
/// </summary>
|
|
|
/// <value>The left position.</value>
|
|
|
public int LeftItem {
|
|
@@ -236,7 +237,7 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Gets the widest item.
|
|
|
+ /// Gets the widest item in the list.
|
|
|
/// </summary>
|
|
|
public int Maxlength => (source?.Length) ?? 0;
|
|
|
|
|
@@ -264,10 +265,12 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Initializes a new instance of <see cref="ListView"/> that will display the contents of the object implementing the <see cref="IList"/> interface,
|
|
|
+ /// Initializes a new instance of <see cref="ListView"/> that will display the
|
|
|
+ /// contents of the object implementing the <see cref="IList"/> interface,
|
|
|
/// with relative positioning.
|
|
|
/// </summary>
|
|
|
- /// <param name="source">An <see cref="IList"/> data source, if the elements are strings or ustrings, the string is rendered, otherwise the ToString() method is invoked on the result.</param>
|
|
|
+ /// <param name="source">An <see cref="IList"/> data source, if the elements are strings or ustrings,
|
|
|
+ /// the string is rendered, otherwise the ToString() method is invoked on the result.</param>
|
|
|
public ListView (IList source) : this (MakeWrapper (source))
|
|
|
{
|
|
|
}
|
|
@@ -296,7 +299,8 @@ namespace Terminal.Gui {
|
|
|
/// Initializes a new instance of <see cref="ListView"/> that will display the contents of the object implementing the <see cref="IList"/> interface with an absolute position.
|
|
|
/// </summary>
|
|
|
/// <param name="rect">Frame for the listview.</param>
|
|
|
- /// <param name="source">An IList data source, if the elements of the IList are strings or ustrings, the string is rendered, otherwise the ToString() method is invoked on the result.</param>
|
|
|
+ /// <param name="source">An IList data source, if the elements of the IList are strings or ustrings,
|
|
|
+ /// the string is rendered, otherwise the ToString() method is invoked on the result.</param>
|
|
|
public ListView (Rect rect, IList source) : this (rect, MakeWrapper (source))
|
|
|
{
|
|
|
Initialize ();
|
|
@@ -306,7 +310,9 @@ namespace Terminal.Gui {
|
|
|
/// Initializes a new instance of <see cref="ListView"/> with the provided data source and an absolute position
|
|
|
/// </summary>
|
|
|
/// <param name="rect">Frame for the listview.</param>
|
|
|
- /// <param name="source">IListDataSource object that provides a mechanism to render the data. The number of elements on the collection should not change, if you must change, set the "Source" property to reset the internal settings of the ListView.</param>
|
|
|
+ /// <param name="source">IListDataSource object that provides a mechanism to render the data.
|
|
|
+ /// The number of elements on the collection should not change, if you must change,
|
|
|
+ /// set the "Source" property to reset the internal settings of the ListView.</param>
|
|
|
public ListView (Rect rect, IListDataSource source) : base (rect)
|
|
|
{
|
|
|
this.source = source;
|
|
@@ -331,13 +337,13 @@ namespace Terminal.Gui {
|
|
|
AddCommand (Command.ToggleChecked, () => MarkUnmarkRow ());
|
|
|
|
|
|
// Default keybindings for all ListViews
|
|
|
- AddKeyBinding (Key.CursorUp,Command.LineUp);
|
|
|
+ AddKeyBinding (Key.CursorUp, Command.LineUp);
|
|
|
AddKeyBinding (Key.P | Key.CtrlMask, Command.LineUp);
|
|
|
|
|
|
AddKeyBinding (Key.CursorDown, Command.LineDown);
|
|
|
AddKeyBinding (Key.N | Key.CtrlMask, Command.LineDown);
|
|
|
|
|
|
- AddKeyBinding(Key.PageUp,Command.PageUp);
|
|
|
+ AddKeyBinding (Key.PageUp, Command.PageUp);
|
|
|
|
|
|
AddKeyBinding (Key.PageDown, Command.PageDown);
|
|
|
AddKeyBinding (Key.V | Key.CtrlMask, Command.PageDown);
|
|
@@ -386,7 +392,8 @@ namespace Terminal.Gui {
|
|
|
Driver.SetAttribute (current);
|
|
|
}
|
|
|
if (allowsMarking) {
|
|
|
- Driver.AddRune (source.IsMarked (item) ? (AllowsMultipleSelection ? Driver.Checked : Driver.Selected) : (AllowsMultipleSelection ? Driver.UnChecked : Driver.UnSelected));
|
|
|
+ Driver.AddRune (source.IsMarked (item) ? (AllowsMultipleSelection ? Driver.Checked : Driver.Selected) :
|
|
|
+ (AllowsMultipleSelection ? Driver.UnChecked : Driver.UnSelected));
|
|
|
Driver.AddRune (' ');
|
|
|
}
|
|
|
Source.Render (this, Driver, isSelected, item, col, row, f.Width - col, start);
|
|
@@ -409,6 +416,8 @@ namespace Terminal.Gui {
|
|
|
/// </summary>
|
|
|
public event Action<ListViewRowEventArgs> RowRender;
|
|
|
|
|
|
+ private string search { get; set; }
|
|
|
+
|
|
|
///<inheritdoc/>
|
|
|
public override bool ProcessKey (KeyEvent kb)
|
|
|
{
|
|
@@ -419,13 +428,37 @@ namespace Terminal.Gui {
|
|
|
if (result != null)
|
|
|
return (bool)result;
|
|
|
|
|
|
+ // Enable user to find & select an item by typing text
|
|
|
+ if (source is IListDataSourceSearchable &&
|
|
|
+ !(kb.IsCapslock && kb.IsCtrl && kb.IsAlt && kb.IsScrolllock && kb.IsNumlock && kb.IsCapslock)) {
|
|
|
+ if (kb.KeyValue >= 32 && kb.KeyValue < 127) {
|
|
|
+ if (searchTimer == null) {
|
|
|
+ searchTimer = new System.Timers.Timer (500);
|
|
|
+ searchTimer.Elapsed += (o, e) => {
|
|
|
+ searchTimer.Stop ();
|
|
|
+ searchTimer = null;
|
|
|
+ search = "";
|
|
|
+ };
|
|
|
+ searchTimer.Start ();
|
|
|
+ }
|
|
|
+ search += (char)kb.KeyValue;
|
|
|
+ var found = ((IListDataSourceSearchable)source).StartsWith (search);
|
|
|
+ if (found != -1) {
|
|
|
+ SelectedItem = found;
|
|
|
+ SetNeedsDisplay ();
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Prevents marking if it's not allowed mark and if it's not allows multiple selection.
|
|
|
+ /// If <see cref="AllowsMarking"/> and <see cref="AllowsMultipleSelection"/> are both <see langword="true"/>,
|
|
|
+ /// unmarks all marked items other than the currently selected.
|
|
|
/// </summary>
|
|
|
- /// <returns></returns>
|
|
|
+ /// <returns><see langword="true"/> if unmarking was successful.</returns>
|
|
|
public virtual bool AllowsAll ()
|
|
|
{
|
|
|
if (!allowsMarking)
|
|
@@ -442,9 +475,9 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Marks an unmarked row.
|
|
|
+ /// Marks the <see cref="SelectedItem"/> if it is not already marked.
|
|
|
/// </summary>
|
|
|
- /// <returns></returns>
|
|
|
+ /// <returns><see langword="true"/> if the <see cref="SelectedItem"/> was marked.</returns>
|
|
|
public virtual bool MarkUnmarkRow ()
|
|
|
{
|
|
|
if (AllowsAll ()) {
|
|
@@ -457,7 +490,7 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Moves the selected item index to the next page.
|
|
|
+ /// Changes the <see cref="SelectedItem"/> to the item at the top of the visible list.
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public virtual bool MovePageUp ()
|
|
@@ -476,7 +509,8 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Moves the selected item index to the previous page.
|
|
|
+ /// Changes the <see cref="SelectedItem"/> to the item just below the bottom
|
|
|
+ /// of the visible list, scrolling if needed.
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public virtual bool MovePageDown ()
|
|
@@ -498,7 +532,8 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Moves the selected item index to the next row.
|
|
|
+ /// Changes the <see cref="SelectedItem"/> to the next item in the list,
|
|
|
+ /// scrolling the list if needed.
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public virtual bool MoveDown ()
|
|
@@ -538,7 +573,8 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Moves the selected item index to the previous row.
|
|
|
+ /// Changes the <see cref="SelectedItem"/> to the previous item in the list,
|
|
|
+ /// scrolling the list if needed.
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public virtual bool MoveUp ()
|
|
@@ -574,7 +610,8 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Moves the selected item index to the last row.
|
|
|
+ /// Changes the <see cref="SelectedItem"/> to last item in the list,
|
|
|
+ /// scrolling the list if needed.
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public virtual bool MoveEnd ()
|
|
@@ -592,7 +629,8 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Moves the selected item index to the first row.
|
|
|
+ /// Changes the <see cref="SelectedItem"/> to the first item in the list,
|
|
|
+ /// scrolling the list if needed.
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public virtual bool MoveHome ()
|
|
@@ -608,23 +646,23 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Scrolls the view down.
|
|
|
+ /// Scrolls the view down by <paramref name="items"/> items.
|
|
|
/// </summary>
|
|
|
- /// <param name="lines">Number of lines to scroll down.</param>
|
|
|
- public virtual bool ScrollDown (int lines)
|
|
|
+ /// <param name="items">Number of items to scroll down.</param>
|
|
|
+ public virtual bool ScrollDown (int items)
|
|
|
{
|
|
|
- top = Math.Max (Math.Min (top + lines, source.Count - 1), 0);
|
|
|
+ top = Math.Max (Math.Min (top + items, source.Count - 1), 0);
|
|
|
SetNeedsDisplay ();
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Scrolls the view up.
|
|
|
+ /// Scrolls the view up by <paramref name="items"/> items.
|
|
|
/// </summary>
|
|
|
- /// <param name="lines">Number of lines to scroll up.</param>
|
|
|
- public virtual bool ScrollUp (int lines)
|
|
|
+ /// <param name="items">Number of items to scroll up.</param>
|
|
|
+ public virtual bool ScrollUp (int items)
|
|
|
{
|
|
|
- top = Math.Max (top - lines, 0);
|
|
|
+ top = Math.Max (top - items, 0);
|
|
|
SetNeedsDisplay ();
|
|
|
return true;
|
|
|
}
|
|
@@ -653,9 +691,10 @@ namespace Terminal.Gui {
|
|
|
|
|
|
int lastSelectedItem = -1;
|
|
|
private bool allowsMultipleSelection = true;
|
|
|
+ private System.Timers.Timer searchTimer;
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Invokes the SelectedChanged event if it is defined.
|
|
|
+ /// Invokes the <see cref="SelectedItemChanged"/> event if it is defined.
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public virtual bool OnSelectedChanged ()
|
|
@@ -673,7 +712,7 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Invokes the OnOpenSelectedItem event if it is defined.
|
|
|
+ /// Invokes the <see cref="OpenSelectedItem"/> event if it is defined.
|
|
|
/// </summary>
|
|
|
/// <returns></returns>
|
|
|
public virtual bool OnOpenSelectedItem ()
|
|
@@ -788,23 +827,15 @@ namespace Terminal.Gui {
|
|
|
|
|
|
return true;
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Implements an <see cref="IListDataSource"/> that renders arbitrary <see cref="IList"/> instances for <see cref="ListView"/>.
|
|
|
- /// </summary>
|
|
|
- /// <remarks>Implements support for rendering marked items.</remarks>
|
|
|
- public class ListWrapper : IListDataSource {
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public class ListWrapper : IListDataSourceSearchable {
|
|
|
IList src;
|
|
|
BitArray marks;
|
|
|
int count, len;
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Initializes a new instance of <see cref="ListWrapper"/> given an <see cref="IList"/>
|
|
|
- /// </summary>
|
|
|
- /// <param name="source"></param>
|
|
|
+ /// <inheritdoc/>
|
|
|
public ListWrapper (IList source)
|
|
|
{
|
|
|
if (source != null) {
|
|
@@ -815,14 +846,10 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Gets the number of items in the <see cref="IList"/>.
|
|
|
- /// </summary>
|
|
|
+ /// <inheritdoc/>
|
|
|
public int Count => src != null ? src.Count : 0;
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Gets the maximum item length in the <see cref="IList"/>.
|
|
|
- /// </summary>
|
|
|
+ /// <inheritdoc/>
|
|
|
public int Length => len;
|
|
|
|
|
|
int GetMaxLengthItem ()
|
|
@@ -869,17 +896,7 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Renders a <see cref="ListView"/> item to the appropriate type.
|
|
|
- /// </summary>
|
|
|
- /// <param name="container">The ListView.</param>
|
|
|
- /// <param name="driver">The driver used by the caller.</param>
|
|
|
- /// <param name="marked">Informs if it's marked or not.</param>
|
|
|
- /// <param name="item">The item.</param>
|
|
|
- /// <param name="col">The col where to move.</param>
|
|
|
- /// <param name="line">The line where to move.</param>
|
|
|
- /// <param name="width">The item width.</param>
|
|
|
- /// <param name="start">The index of the string to be displayed.</param>
|
|
|
+ /// <inheritdoc/>
|
|
|
public void Render (ListView container, ConsoleDriver driver, bool marked, int item, int col, int line, int width, int start = 0)
|
|
|
{
|
|
|
container.Move (col, line);
|
|
@@ -897,11 +914,7 @@ namespace Terminal.Gui {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Returns true if the item is marked, false otherwise.
|
|
|
- /// </summary>
|
|
|
- /// <param name="item">The item.</param>
|
|
|
- /// <returns><c>true</c>If is marked.<c>false</c>otherwise.</returns>
|
|
|
+ /// <inheritdoc/>
|
|
|
public bool IsMarked (int item)
|
|
|
{
|
|
|
if (item >= 0 && item < count)
|
|
@@ -909,25 +922,40 @@ namespace Terminal.Gui {
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Sets the item as marked or unmarked based on the value is true or false, respectively.
|
|
|
- /// </summary>
|
|
|
- /// <param name="item">The item</param>
|
|
|
- /// <param name="value"><true>Marks the item.</true><false>Unmarked the item.</false>The value.</param>
|
|
|
+ /// <inheritdoc/>
|
|
|
public void SetMark (int item, bool value)
|
|
|
{
|
|
|
if (item >= 0 && item < count)
|
|
|
marks [item] = value;
|
|
|
}
|
|
|
|
|
|
- /// <summary>
|
|
|
- /// Returns the source as IList.
|
|
|
- /// </summary>
|
|
|
- /// <returns></returns>
|
|
|
+ /// <inheritdoc/>
|
|
|
public IList ToList ()
|
|
|
{
|
|
|
return src;
|
|
|
}
|
|
|
+
|
|
|
+ /// <inheritdoc/>
|
|
|
+ public int StartsWith (string search)
|
|
|
+ {
|
|
|
+ if (src == null || src?.Count == 0) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i = 0; i < src.Count; i++) {
|
|
|
+ var t = src [i];
|
|
|
+ if (t is ustring u) {
|
|
|
+ if (u.ToUpper ().StartsWith (search.ToUpperInvariant ())) {
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ } else if (t is string s) {
|
|
|
+ if (s.ToUpperInvariant().StartsWith (search.ToUpperInvariant())) {
|
|
|
+ return i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/// <summary>
|