How can i implement my Combobox TextSearch using contains
instead of StartsWith
<rf:ComboBox Grid.Row="1"
Grid.Column="5"
Width="200"
ItemsSource="{Binding Source={StaticResource AccountProvider}}"
DisplayMemberPath="Description"
SelectedValuePath="IndRekId"
IsEmptyItemVisible="True"
SelectedValue="{Binding Id, UpdateSourceTrigger=PropertyChanged}"
IsTextSearchEnabled="True"
TextSearch.TextPath="Description"
IsEditable="True"/>
The search function works but i need to match on substrings
Here I have an example in MVVM framework.
my xaml file:
<ComboBox Name="cmbContains" IsEditable="True" IsTextSearchEnabled="false" ItemsSource="{Binding pData}" DisplayMemberPath="wTitle" Text="{Binding SearchText ,Mode=TwoWay}" >
<ComboBox.Triggers>
<EventTrigger RoutedEvent="TextBoxBase.TextChanged">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsDropDownOpen">
<DiscreteBooleanKeyFrame Value="True" KeyTime="0:0:0"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ComboBox.Triggers>
</ComboBox>
my cs file:
//ItemsSource - pData
//There is a string attribute - wTitle included in the fooClass (DisplayMemberPath)
private ObservableCollection<fooClass> __pData;
public ObservableCollection<fooClass> pData {
get { return __pData; }
set { Set(() => pData, ref __pData, value);
RaisePropertyChanged("pData");
}
}
private string _SearchText;
public string SearchText {
get { return this._SearchText; }
set {
this._SearchText = value;
RaisePropertyChanged("SearchText");
//Update your ItemsSource here with Linq
pData = new ObservableCollection<fooClass>{pData.ToList().Where(.....)};
}
}
You can see the editable comboBox is binding to the string (SearchText) Once there is a TextChanged event the drop down is shown and the Two way binding update the value. The ItemsSource changed in the cs file while it goes into the set{}; syntax.
https://gist.github.com/tonywump/82e66abaf71f715c4bd45a82fce14d80
This sample look like "TextSearch"
In XAML file you should add only one attribute to combobox "TextContainSearch.Text":
<ComboBox ItemsSource="{Binding Model.formListIntDeviceNumbers}" SelectedItem="{Binding Path=Model.selectedDeviceNumber, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="DeviceNumber" IsEditable="True" c:TextContainSearch.Text="DeviceNumber">
And we should add using in the header of XAML file:
xmlns:c="clr-namespace:Adaptive.Controls.Extension"
And C# code in *.cs file:
using System;
using System.Windows;
using System.Windows.Controls;
namespace Adaptive.Controls.Extension
{
public sealed class TextContainSearch : DependencyObject {
public static void SetText(DependencyObject element, string text) {
var controlSearch = element as Control;
if (controlSearch != null)
controlSearch.KeyUp += (sender, e) =>
{
if (sender is ComboBox){
var control = sender as ComboBox;
control.IsDropDownOpen = true;
var oldText = control.Text;
foreach(var itemFromSource in control.ItemsSource){
if (itemFromSource != null)
{
Object simpleType = itemFromSource.GetType().GetProperty(text).GetValue(itemFromSource, null);
String propertOfList = simpleType as string;
if (!string.IsNullOrEmpty(propertOfList) && propertOfList.Contains(control.Text))
{
control.SelectedItem = itemFromSource;
control.Items.MoveCurrentTo(itemFromSource);
break;
}
}
}
control.Text = oldText;
TextBox txt = control.Template.FindName("PART_EditableTextBox", control) as TextBox;
if (txt != null)
{
txt.Select(txt.Text.Length, 0);
}
}
};
}
}
}
Try this:
<ComboBox Padding="3,5" MinWidth="150" SelectedItem="{Binding NewBoxRequest}"
ItemsSource="{Binding Requests}" DisplayMemberPath="SN" IsEditable="True"
StaysOpenOnEdit="True"
Text="{Binding SnFilter,UpdateSourceTrigger=PropertyChanged}">
</ComboBox>
view model:
private string snFilter;
public string SnFilter
{
get { return snFilter; }
set
{
snFilter = value;
RaisePropertyChanged();
RaisePropertyChanged(nameof(Requests));
}
}
private List<Request> requests;
public List<Request> Requests
{
get => string.IsNullOrEmpty(SnFilter) || requests.Any(r => r.SN == SnFilter)
? requests
: requests.Where(r => r.SN.Contains(SnFilter)).ToList();
set
{
requests = value;
RaisePropertyChanged();
}
}
There is no way to replace string.StartsWith() with string.Contains(). You have to write your custom ComboBox.
This article may help you: http://www.codeproject.com/Tips/631196/ComboBox-with-Suggest-Ability-based-on-Substring-S
I could not get the "Set" syntax to work in my C# system, so here is a small takeoff to Wu's answer above (this is in a custom control):
<ComboBox IsEditable="True"
IsTextSearchEnabled="false"
ItemsSource="{Binding pData, RelativeSource = {RelativeSource TemplatedParent}}"
DisplayMemberPath="description"
Text="{Binding SearchText , RelativeSource = {RelativeSource TemplatedParent}, Mode=TwoWay}" >
<ComboBox.Triggers>
<EventTrigger RoutedEvent="TextBoxBase.TextChanged">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="IsDropDownOpen">
<DiscreteBooleanKeyFrame Value="True" KeyTime="0:0:0"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ComboBox.Triggers>
</ComboBox>
In the custom control:
private async void _Loaded(object sender, RoutedEventArgs e)
{
var n = await InitializeLabTests;
allTests = new ObservableCollection<CommonProcedure>(n);
pData = new ObservableCollection<CommonProcedure>(n);
}
//ItemsSource - pData
//There is a string attribute - wTitle included in the fooClass (DisplayMemberPath)
private ObservableCollection<CommonProcedure> __pData;
public ObservableCollection<CommonProcedure> pData
{
get { return __pData; }
set { __pData = value; RaisePropertyChanged(); }
}
private string _SearchText;
public string SearchText
{
get { return _SearchText; }
set
{
_SearchText = value; RaisePropertyChanged();
//Update your ItemsSource here with Linq
pData = new ObservableCollection<CommonProcedure>
(
allTests.Where(q => q.description.Contains(SearchText))
);
}
}
The only significant difference being in the SearchText setter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With