How to apply Search in Editable Combobox in WPF using MVVM - c#

I have editable combobox in WPF. which is having list of order number.
I need to implement below scenario in my code.
The user can fill the starting of order number, and, the system propose the close order number available in the dropdown list.
Can anyone suggest how to do that?
In My Viewmodel i have written:
public void _fillREOrderNumbers()
{
List<FinishedReprintingOrderNumber> orders = _finishedProductReprintService.GetFinishedProductReprintbyOrder().ToList();
foreach (var item in orders)
{
ReOrders.Add(item);
}
}
This is loading the order number in drop down.
View or XAML:
<ComboBox x:Name="cbOFab" HorizontalAlignment="Left" Margin="373,81,0,0"
VerticalAlignment="Top" Width="262" IsEditable="True"
ItemsSource="{Binding ReOrders, Mode=TwoWay}" DisplayMemberPath="codOrder" SelectedItem="{Binding
ReSelectedOrder}" Background="{DynamicResource dgridRowColor}" />
Till Now,
I am able to populate the order number in my combo box but I am not aware how to search inside it.

I have implemented filtering of items in ComboBox this way.
Here is XAML:
<ComboBox
MinWidth="200"
ItemsSource="{Binding Path=Shops.View, RelativeSource={RelativeSource TemplatedParent}}"
DisplayMemberPath="NameExtended"
SelectedItem="{Binding Path=SelectedShop, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
IsTextSearchEnabled="False"
IsEditable="True"
IsDropDownOpen="{Binding Path=ComboOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
StaysOpenOnEdit="True"
Text="{Binding Path=SearchText, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyUp">
<i:InvokeCommandAction
Command="{Binding Path=FilterCommand, RelativeSource={RelativeSource TemplatedParent}}"
/>
</i:EventTrigger>
</i:Interaction.Triggers>
You need all lines from IsTextSearchEnabled and below.
When you press any key in combo box, it opens in up and filters items in it, using property SearchText bound to ComboBox.Text.
Here is the view model code:
public string SearchText { get; set; }
private List<Shop> _shops;
protected void FilterShops()
{
ComboOpen = true;
if (!string.IsNullOrEmpty(SearchText))
{
Shops.UpdateSource(_shops.Where(s => s.NameExtended.ToLower().Contains(SearchText.ToLower())));
}
else
{
Shops.UpdateSource(_shops);
}
OnPropertyChanged("Shops");
}

Related

On wpf MVVM combobox dropdownopen disable selected text

I have a compobox that I filter when writing and I open dropdown List
The problem occurs when you open dropdown where it automatically selects text
That is, he writes directly on it deletes the first letter that specifies and the filtering process is not done correctly I want to cancel the relationship between opening dropdown and select text
<ComboBox MinWidth="300" Margin="5,0,0,0"
DisplayMemberPath="NoName" IsEditable="True" IsTextSearchEnabled="False"
ItemsSource="{Binding VData.ItemsView}"
SelectedIndex="{Binding ItemIndex, Mode=TwoWay}"
SelectedValue="{Binding ModelTable.ItemId, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
SelectedValuePath="Id" TabIndex="4"
Text="{Binding ItemNoName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
IsDropDownOpen="{Binding ItemDropDown}">
*******
private string? _itemnoname;
public string? ItemNoName
{
get => _itemnoname;
set => Set(ref _itemnoname, value, ItemOpen);
}
private void ItemOpen(string? obj)
{
if (VEnable.Item)
{
if (!string.IsNullOrWhiteSpace(obj)) ItemDropDown = true;
VData.RefreshItemsView(obj);
}
}

One view, two Comboboxes with filters interferes each other filters

I've created a FilterCombobox that inherits from Combobox.
This FilterCombobox filters the result based on the users input.
In my view I have two of these FilterCombobox's and they reference the same ObserveableCollection.
I can filter in one FilterCombobox1 without filter the other, but
When I change focus to the next FilterCombobox2, the FilterCombobox1 is filtered according to the filter applied in FilterCombobx2 after the third'ish letter (looks like this a recurring pattern)
If I have two seperate ObserveableCollection then this issue does not invoke, so I mistake that my filter method does something to the actual ObserveableCollection.
Filter method:
private void SetFilterToTextInput()
{
Items.Filter += a =>
{
var propertyString = GetPropertyString(a);
if (propertyString.ToUpper().Contains(Text.ToUpper()))
return true;
return false;
};
}
This is my XAML implementation of these two FilterComboboxes:
<Controller:FilterComboBox
ItemsSource="{Binding Path=Collection,UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"
DisplayMemberPath="Name"
SelectedValue="{Binding Left, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
Width="135"
/>
<TextBlock Margin="0,5,5,0" FontSize="16" VerticalAlignment="Center" >-</TextBlock>
<Controller:FilterComboBox
ItemsSource="{Binding Path=Collection, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}"
DisplayMemberPath="Name"
SelectedValue="{Binding Right, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"
Width="135"
/>

Delay in getting text on text box textchanged event - Windows phone

I created a TextBox. I wrote a TextChanged event in view model. The problem is, when I type 'a' in the TextBox, in the TextChanged event, I am getting "". Then if I type next letter 'b', I am getting the previous result 'a' and If I type the next letter 'c', I am getting 'ab' as result. Why is one char delay in the TextChanged event?
Here is my XAML code:
<toolkit:PhoneTextBox Visibility="{Binding IsSearchBoxVisible,Converter={StaticResource BoolToVisibilityConverter}}" TextChanged="txtboxPhoneContacts_TextChanged" Grid.Row="2" Width="450" FontSize="28" Foreground="Black" x:Name="txtboxPhoneContacts" VerticalContentAlignment="Center" Background="LightGray" Hint="{Binding Localizedresources.SearchContactsText,Source={StaticResource LocalizedStrings}}" Text="{Binding PhoneContactSearchText,Mode=TwoWay,UpdateSourceTrigger=Explicit}" Style="{StaticResource SearchTextBoxStyle}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<i:InvokeCommandAction Command="{Binding PhoneBookTextBoxTextChanged}" CommandParameter="{Binding Text,ElementName=txtboxPhoneContacts,BindsDirectlyToSource=True}"></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
<i:Interaction.Behaviors>
<controls:UpdateOnTextChangedBehavior></controls:UpdateOnTextChangedBehavior>
</i:Interaction.Behaviors>
</toolkit:PhoneTextBox>
My ViewModel.cs
private void OnPhoneBookTextBoxTextChanged(Object obj)
{
if (obj != null)
{
String text = obj.ToString();
searchResults = new ObservableCollection<PhoneBookEntity>(
from item in PhoneContactsList
where item.PhoneContactName.Contains(text)
select item);
}
}
Any suggestions is highly appreciated.

Editable WPF ComboBox does not fire PropertyChanged

I have a not editable ComboBox to display all tables of and SQL Database.
<ComboBox Grid.Column="1"
Grid.Row="2"
Height="23"
Margin="3,3,3,3" Name="cbLogTable" VerticalAlignment="Top"
ItemsSource="{Binding}"
TextSearch.TextPath="TABLE_NAME"
SelectedValue="{Binding Path=LogTable, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, ValidatesOnDataErrors=True}"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path=TABLE_NAME}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
The property of the containing UserControl looks like this and also implements the INotifyPropertyChanged:
public string LogTable
{
get
{
return _logTable;
}
set
{
if (_logTable == value) return;
_logTable = value;
OnPropertyChanged("LogTable");
}
}
I use the following data binding to fill the ComboBox:
private void UpdateLogTable()
{
var connection = new SqlConnection(_connectionString);
connection.Open();
DataTable t = connection.GetSchema("Tables");
cbLogTable.DataContext = t;
connection.Close();
}
But I don't receive a PropertyChanged notification on changing the selected value of the ComboBox. Where is my fault?
In the binding of SelectedValue:
SelectedValue="{Binding Path=LogTable,
UpdateSourceTrigger=PropertyChanged,
Mode=TwoWay,
ValidatesOnDataErrors=True,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type UserControl}}}"
Otherwise, the binding is looking for LogTable property on the DataTable type (which is the DataContext for the Combobox), and fails silently.

Binding ComboBox ItemsSource in DataGrid RowDetailsTemplate

I am trying to bind an ItemsSource to a ComboBox in a RowDetailsTemplate. If I place a ComboBox outside the grid it works fine. I think this is occureing because of the ItemsSource property on the grid may be throwing off the ComboBox within the RowDetailsTemplate. XAML is below any thoughts?
Categories and CatTypes are two different ObservableCollections.
No error is occurring; the ComboBox just appears empty.
<ComboBox ItemsSource="{Binding CatTypes}"></ComboBox>
<my:DataGrid Name="gridProds" AutoGenerateColumns="False"
AlternatingRowBackground="Gainsboro" ItemsSource="{Binding Categories}">
<my:DataGrid.Columns>
<my:DataGridTextColumn x:Name="CatId" Header="CatID" Width="Auto" Binding="{Binding CategoryID}" />
<my:DataGridTextColumn Header="CatName" Width="Auto" Binding="{Binding CategoryName}" />
</my:DataGrid.Columns>
<my:DataGrid.RowDetailsTemplate>
<DataTemplate>
<Border>
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label>ID:</Label>
<TextBox Name="txtGridCatId" Text="{Binding CategoryID}"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label>Category Type:</Label>
<ComboBox ItemsSource="{Binding CatTypes}"></ComboBox>
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
</my:DataGrid.RowDetailsTemplate>
</my:DataGrid>
There is a class in the called DataSource in which the following is done:
private ObservableCollection<string> _cattypes = new ObservableCollection<string> { };
public ObservableCollection<string> CatTypes
{
get
{
_cattypes = new ObservableCollection<string> { };
SqlConnection con = new SqlConnection("MyConnStringHere;");
SqlCommand cmd = new SqlCommand("Select ID, CatType from PfCategoryType ORDER BY CatType", con);
con.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
string CatType = (string)rdr["CatType"];
_cattypes.Add(CatType);
}
con.Close();
return _cattypes;
}
}
In the MainWindow.xaml.cs I have:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataSource dataSource = new DataSource();
this.DataContext = dataSource;
}
}
If you checked the debug output in VS you would see the actual binding error. Most likely below code will fix it for you.
<ComboBox ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=CatTypes}" />
If you can't get RelativeSource to work then use names. The property CatTypes is a property of some class which you created an object for and set as datacontext to some control. Just give that control a name (for example myControl) and bind like this:
<ComboBox ItemsSource="{Binding ElementName=myControl, Path=CatTypes}" />
If that don't work you need to post more of your code to figure out what you are doing wrong.
What happens if you try this?
<ComboBox DataContext="{Binding DataContext, ElementName=myControl}" ItemsSource="{Binding CatTypes}" />
(Of course you'd rename "myControl" to match the name of your window.)
Here, we're setting the data context of the combo box to be the same as the data context of the window. Since this is also the same data context of the first combo box in your XAML, I imagine the second combo box will start behaving like the first. (Although I worry that this will result in some unnecessary database connections, one per grid row.)
On second thought, if you need to set other properties in the context of the row, you won't want to set the data context of the entire ComboBox. In that case, I'd try something like this.
<ComboBox ItemsSource="{Binding ElementName=myControl, Path=DataContext.CatTypes}" SelectedItem="{Binding CategoryType}" />

Categories

Resources