1

With this code if I type mixed it finds Mixed content okay.

How can I modify this to search mid string for example content and have the dropdown displayed with the matching items that are in ComboBox?

Add-Type -AssemblyName System.Windows.Forms

$Form                        = New-Object System.Windows.Forms.Form
$Form.StartPosition          = 'CenterScreen'

$cbSearch                    = New-Object System.Windows.Forms.ComboBox
$cbSearch.Width              = 280

# This will allow autocomplete but not for mid string.
$cbSearch.AutoCompleteSource = 'ListItems'
$cbSearch.AutoCompleteMode   = 'Append'

$cbSearch.Items.AddRange(@('Mixed content', 'More stuff', 'ANOTHER THING CONTENT', 'Item ?', 'Mixed item'))
$cbSearch.Add_SelectedValueChanged({ selectChanged $this $_ })

# Event handler action for the cbSearch control.
function selectChanged ($sender, $event) {
  [void][system.windows.forms.messagebox]::Show($cbSearch.Text)
}

$Form.Controls.Add($cbSearch)
[void]$Form.ShowDialog()

The result I was after

If I search content then the two items are shown.

enter image description here


EDIT:

Here's my latest attempt which filters how I would like using the .Add_TestUpdate callback but it results in some errors in the console Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. and only allowing one letter to be typed into the box.

Perhaps someone may know how to fix this issue or perhaps I'm barking up the wrong tree.

Add-Type -AssemblyName System.Windows.Forms

$Form                        = New-Object System.Windows.Forms.Form
$Form.StartPosition          = 'CenterScreen'

$cbSearch                    = New-Object System.Windows.Forms.ComboBox
$cbSearch.Width              = 280

# This will allow autocomplete but not for mid string.
$cbSearch.AutoCompleteSource = 'ListItems'
$cbSearch.AutoCompleteMode   = 'SuggestAppend'

$cbArr = @('Mixed', 'More stuff CONTENT', 'ANOTHER THING cONTENT', 'Item ?', 'Mixed item')
$cbSearch.Items.AddRange($cbArr)

# Create a new array for found items.
$foundItems = @()

# TextUpdate callback.
# In an attempt to get mid string searching to work.
$cbSearch.Add_TextUpdate(
{

 $foundItems = $script:cbArr | Where-Object {$_ -Match [regex]::Escape($cbSearch.Text)}

 # If there's found items, begin the update, clear the filter, add the range, end
 # update and the set the dropdown to its downed state.
 if ($foundItems.length -gt 0) {
  $cbSearch.BeginUpdate()
  $cbSearch.Items.Clear()
  $cbSearch.Items.AddRange($foundItems)
  $cbSearch.EndUpdate()
  $cbSearch.DroppedDown = $true
  } else {
    # If no items are found, do this.
    $cbSearch.DroppedDown = $false
    $cbSearch.BeginUpdate()
    $cbSearch.Items.Clear()
    $cbSearch.Items.AddRange($script:cbArr)
    $cbSearch.EndUpdate()
  }

}
)

# Add controls and start form.
$Form.Controls.Add($cbSearch)
[void]$Form.ShowDialog()
Ste
  • 1,729
  • 1
  • 17
  • 27
  • You'll probably need to override `KeyPress` & `TextChanged` events of your `ComboBox`, not sure if this would work on PS. You'll need to translate from `C#` to `PS` syntax. See https://stackoverflow.com/questions/2259067/override-winforms-combobox-autocomplete-suggest-rule – Santiago Squarzon Apr 30 '21 at 16:55
  • I'm not to versed on C#. I found that if I use `$cbSearch.AutoCompleteMode = 'SuggestAppend'` then it'll populate the box but not during a mid search. It'll work when I search `m` which displays [this](https://i.imgur.com/OqM1NAr.png) but not `content`. – Ste Apr 30 '21 at 19:41
  • Yes, `SuggestAppend` and `Suggest` will only autocomplete words that start with what you're typing but will not find a string contained in a list. – Santiago Squarzon Apr 30 '21 at 19:44
  • At least for now `SuggestAppend` will drop the box down until I or someone comes along with an answer. – Ste Apr 30 '21 at 20:10
  • Yep, I usually use `SuggestAppend` for `DataGridView` too, but pretty interested if there is a solution to your problem in PowerShell. – Santiago Squarzon Apr 30 '21 at 20:20
  • 1
    You are trying to recreate what Out-GridView natively does. Yet OGV displays all options by default. Your current use case is a bad UX/UI design. You are forcing a user to guess at what is in the list. The item Santiago suggested, which forces the dropdown, as you've discovered, is a more prudent option. Yet, OGV is using combobox and data binding/filtering like this [Using a Combo Box to search as you type](https://www.microsoft.com/en-us/microsoft-365/blog/2012/05/03/using-a-combo-box-to-search-as-you-type/), which is what you are trying to achieve in a combobox alone. – postanote Apr 30 '21 at 20:22
  • 1
    There are other text search properties that can be used, and MS documents those. [ComboBox.IsTextSearchEnabled Property](https://learn.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.combobox.istextsearchenabled?view=winrt-19041) and [ComboBox.FindString Method](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.combobox.findstring?view=net-5.0), [ComboBox.FindStringExact Method](https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.combobox.findstringexact?view=net-5.0), etc. – postanote Apr 30 '21 at 20:44
  • Agreed, so I've found this which states something very simlar to what @postanote is saying "...From a UI design perspective, if you have so many items in a combobox that a user needs autocomplete that looks at substrings to filter down the choices, it's a big hint that a combobox is not the correct control to use, and that you need to re-design your UI" link: https://csharpforums.net/threads/autocomplete-in-combobox-matching-any-part-of-string.4928/ – Santiago Squarzon Apr 30 '21 at 21:05
  • I don't want to get into a debate on what's best practice and get off-topic. If I type a single word of half or one it's going to narrow it down to a usable state. Hence the reason for mid string searching to allow a fuzzy type search. It works well for google chrome when you type something into the address bar, so why not little old me? – Ste Apr 30 '21 at 23:53
  • `ComboBox.FindString` looks promising, thanks. I'll look into that tomorrow. – Ste May 01 '21 at 00:01
  • As for this `It works well for google chrome when you type something into the address bar`; this is not an apples-to-apples comparison. There are whole optimized libraries behind all browsers the do this. These are not client-side calls. These are calls to backend analytic component operations/services. Meaning custom code, not simple settings. For example [PowerApps Combobox - Search, Filter](https://www.youtube.com/watch?v=pjs0ZsnJZXo). Note it is the component that provides this; just like this one: [Searchable Dropdown for VBA UserForm](https://www.youtube.com/watch?v=gkLB-xu_JTU). – postanote May 01 '21 at 00:26
  • I've added my latest attempt at trying to get this to work in the question. It uses the `Add_TextUpdate` callback. It does have its issues described in the post. Still, it might help someone come up with an idea on how to fix it. – Ste May 02 '21 at 11:45
  • As this this... `ComboBox.FindString looks promising,`, to use such approaches for your use case, it is goging to require custom code. [Depending on what you are really after, it could be as close as 100 lines](https://code-examples.net/en/q/1a487dc). Point of note, you do realize there are 3 types of combo boxes (simple/drop/list), and each have limits. What you are after, is not a feature native comboboxes. Hence the need for custom code or purchasing 3rdP compnents (like Telerik), which provide it. Lastly, WPF is better for such things. Again, I've done this stuff, and argh, just a painl. – postanote May 03 '21 at 03:09

0 Answers0