I have a combobox in WPF. I put the TextBox in it as ComboBoxItem. Now I want the ComboBoxItem to be filtered when I type in TextBox:
<ComboBox Grid.Column="1" Grid.Row="1" Margin="23,8,22,29" Name="comboBox1" DropDownOpened="comboBox1_DropDownOpened">
<ComboBoxItem>
<TextBox Name="texcombo" Width="90" Foreground="Gray" GotFocus="texcombo_GotFocus" KeyDown="texcombo_KeyDown" TextChanged="texcombo_TextChanged" >جستجو</TextBox>
</ComboBoxItem>
<ComboBoxItem>سلام</ComboBoxItem>
<ComboBoxItem>خوبی</ComboBoxItem>
<ComboBoxItem>عرض ادب</ComboBoxItem>
<ComboBoxItem>سپاسگذارم</ComboBoxItem>
<ComboBoxItem>مرسی</ComboBoxItem>
</ComboBox>
How can i do this?
the way you are implementing the Textbox inside ComboBox is wrong. First of all, you should change the Combobox default template to show a specific Textbox inside it instead of putting the Textbox inside items. Then you should bind an observable collection (for data) to ComboBox items. Now you can filter the ObservableCollection based on TextBox TextChanged event or command.
Related
Relatively new to WPF and binding. I have a Listbox filled with values. When a user selects a certain value I want to display details of that value over several labels and a textbox. The current LINQ query that fills my listbox list gets the whole table, so the data is inside that list. How do I go around passing the details of the selected value inside of a label?
My current code for the listbox is :
<ListBox x:Name="LBController" Grid.Column="1" HorizontalAlignment="Left" Grid.RowSpan="6" Grid.Row="1"
ItemsSource ="{Binding AllControllers}" SelectedValue="{Binding SelectedControllerID}"
SelectedValuePath="Id" DisplayMemberPath="Name" >
</ListBox>
If a value inside of the listbox is selected, I would like its name to be displayed on a seperate label
<Label x:Name="lbl_controllername"
Content="Controller Naam" HorizontalAlignment="Left" VerticalAlignment="Top"
Grid.Row="1" Grid.Column="2" FontFamily="Corsiva" FontSize="11" Margin="40,0,0,0"/>
EDIT : Thanks for the answers everyone. This does however seem to prove difficult when doing the same thing with a control that has a function behind it.
<TextBox x:Name="txt_CodeDetail"
TextWrapping="Wrap"
AcceptsReturn="True"
FontFamily="Corsiva"
FontSize="11"
Text="{Binding ControllerCode, Mode=TwoWay}"/>
For example I have a textbox, the text inside of it is converted into a string for a function the app does. This string is called ControllerCode. This was done by copy-pasting the code before but I want the textbox to be filled with a selected property from the value inside the listbox.
I can't use
Text="{Binding SelectedItem.Property Elementname=LBController}"
as that would get rid of Controllercode and ruin the function. How can I bind the textbox text to the selecteditem as well as maintain the string that is formed with controllercode?
If you need to display several properties of an element in some area of the window, then it is easier in this area to set a panel in which the data context is bound to the selected element.
And inside this panel, set a set of elements to represent the properties of the selected element.
Example:
<StackPanel DataContext="{Binding SelectedItem, ElementName=LBController}">
<TextBlock Text="{Binding FirstProperty}"/>
<TextBlock Text="{Binding SecondProperty}"/>
<!--Other elements-->
</StackPanel>
I have a ComboBox with a Textblock and a Checkbox displayed to allow me to set a view model boolean property based off the checkbox.
View Code
<ComboBox HorizontalAlignment="Left" IsEditable="True" IsReadOnly="True" Text="-- Filter Columns --">
<ComboBoxItem>
<ComboBoxItem.ContentTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Description"/>
<CheckBox IsChecked="{Binding DescriptionHeaderVisibility}"/>
</StackPanel>
</DataTemplate>
</ComboBoxItem.ContentTemplate>
</ComboBoxItem>
</ComboBox>
View Model Property
public bool DescriptionHeaderVisibility
{
get => _descriptionHeaderVisibility;
set => Set(ref _descriptionHeaderVisibility, value);
}
Useful information
I am using MVVM Light
If I do the exact same check box binding somewhere else on the page, it works and notifies my view model of the change.
Binding only does not work within the templated combo box
I am not sure why the binding is not working within the combo box template? Am I just missing something here that I don't know about? If I can get this binding to work properly the plan is to add another few rows of text blocks and check boxes all bound to different boolean properties in my view model.
Picture of drop down box
The problem is, you are using a ContentTemplate, but you do not give it any Content to display. If you just want to use the surrounding DataContext, you could write
<ComboBoxItem Content="{Binding .}">
Inspired by this answer to a similar question.
I have a collection of Contact objects that I've bound as follows in a WPF form:
<ComboBox Name="Name"
Text="{Binding Path=Contact.FullName}"
ItemsSource="{Binding ContactsCollection}"
SelectedItem="{Binding Path=Contact, Mode=TwoWay}"
IsEditable="true"
IsTextSearchEnabled="True"
TextBoxBase.TextChanged="Name_TextChanged"/>
<TextBox Name="Position" Text="{Binding Path=Contact.Position}"/>
<TextBox Name="Phone" Text="{Binding Path=Contact.PhoneNumber}"/>
I'd like the contact to be selected when the user starts typing in the combo 'IsTextSearchEnabled=true'.
The problem is that I'd like the items in the collection to remain read-only. Once a contact has been selected, any text deletes or additions modify the contact name in the collection.
How can I bind a collection to a combobox, enable search and prevent edits to the collection?
I could be missing something here, but if you don't want an editable ComboBox, try not setting the ComboBox.IsEditable property to True. Using this simple code, I can display items in a ComboBox and make selections by typing (when the ComboBox is focused) without editing anything:
<ComboBox ItemsSource="{Binding Items}" IsTextSearchEnabled="True" Height="25" />
Thanks for your input. It sorted me out. Removing the SelectedItem property and setting Position and PhoneNumber in the PropertyChanged event was what I needed.
I'm using a combobox to show categories a user can choose.
All those items have the id as the SelectedValuePath so I can easly get those when the user makes a selection.
<ComboBox Grid.Column ="1" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Name="cboCategorieen" ItemsSource="{Binding}" DisplayMemberPath="naam" SelectedValuePath="id" />
But how can I change the selection of the combobox when I have the id of the chosen selection (SelectedValuePath)?
This code doesn't do anything and just keeps selecting the first one.
cboCategorieen.SelectedValuePath = Convert.ToString(artikelWijzigen.categorie);
To conclude:
How can I change the selection of the combobox to the one matching the id?
I would suggest you to follow MVVM, Still the answer for your question would be Say if you have a ItemsSource like this,
ObservableCollection<YourComboBoxClass> wsWebshopMRentals;
You can set the selectedItem of combobox like this,
cboCategorieen.SelectedValue = wsWebshopMRentals.FirstOrDefault(x => x.Id == YourID).naam;
I have a ComboBox in WPF which is databound, and has data template which controls how each of the items is displayed. I have made it so that each item is displayed with two bits of text (for the Name and Path properties) and one image (for the Icon property).
At the moment when I select an item from the ComboBox the textbox bit of the ComboBox just changes to say "TestWPF.Result" which is the name of the class which I have populated the ComboBox with.
I'm interested in one (or both) of two things:
How do I change it so that it displays the value of one of the fields there (eg. so it shows the value of the Name field rather than the name of the class)?
Is it possible get it to use the same DataTemplate there as in the list of items, so that once I have selected an item it displays in the closed ComboBox the same way as it looks in the list of items. Basically I've got a DataTemplate called ShowResults and a ComboBox which uses that template. I've also added in a separate ContentControl which I've got to show the details of the selected item in the ComboBox, but I want to get that to replace the textbox in the ComboBox.
Update:
Thanks for the first answer. I've tried using a separate ContentControl, as you've described, and it works fine. The question now is how to replace the textbox part of the ComboBox with this ContentControl. Any hints on that would be most welcome.
Also, is it possible to replace the textbox bit of the ComboBox control with a mixture of the ContentControl and a textbox, so that I can still type in the textbox to help select items from the ComboBox, but then when I close the dropdown the rest ContentControl bit will be populated with the rest of the text and the icon. Hope that makes sense - ask questions if it doesn't!
Code:
I've been asked to post my code - so here it is. I've tried to remove things that I know are definitely not relevant, but I'm not sure exactly what is relevant so when in doubt I've left things in.
<Window x:Class="TestWPF.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:custom="clr-namespace:TestWPF"
Title="Window1" Height="300" Width="843" Loaded="Window_Loaded">
<Window.Resources>
<DataTemplate x:Key="ShowResult" DataType="TestWPF.Result">
<StackPanel Margin="5" Orientation="Horizontal">
<Image Width="32" Height="32" Source="{Binding Path=Image}"/>
<StackPanel Margin="5">
<TextBlock FontWeight="Bold" Text="{Binding Path=Name}"/>
<TextBlock Text="{Binding Path=Path}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</Window.Resources>
<Grid Width="786">
<Button Height="23" HorizontalAlignment="Right" Margin="0,24,166,0" Name="btnTest" VerticalAlignment="Top" Width="75" Click="btnTest_Click">Add</Button>
<ComboBox StaysOpenOnEdit="True" DropDownClosed="comboBox1_DropDownClosed" PreviewTextInput="comboBox1_PreviewTextInput" SelectionChanged="comboBox1_SelectionChanged" ItemTemplate="{StaticResource ShowResult}" Margin="259,109,22,89" Name="comboBox1" IsEditable="True" />
<ContentControl Height="50" Margin="268,0,22,21" Name="contentControl1" VerticalAlignment="Bottom" Content="{Binding ElementName=comboBox1,Path=SelectedValue}" ContentTemplate="{StaticResource ShowResult}"/>
</Grid>
You got the binding part right - binding to the data and using a DataTemplate to display the source the way you want to.
As to your second question, a way to do it would be to use a ComboBox with IsEditable="True" as you have, and withing the TextChanged event handler check if the comboBox.Items contains the new value, if not check use Linq to seach for a match:
if (comboBox.Items.Contains(e.NewValue))
return;
var matches =
with comboBox.Items
select item
where item.BeginsWith(e.NewValue);
if (matches.Count > 0)
comboBox.SelectedItem = matches.First();
Just place the Property Binding expression to the textBox,You dont need to apply template.
Another way to get exact Data template, Place a ContentControl in the place of textBox and assign the same DataTemplate (say x:Name="robinTemplate")
<ContentControl Content="{Binding ElementName=cmbBox,Path=SelectedValue}" ContentTemplate="{StaticResource robinTemplate}"/>
For making the Selected content display in the same way :
Create a copy of the combobox control template and you will find a ContentPresenter there. Replace that with the ContentControl.. This is not the right solution though.