Which tool is the best option for doing search in Datagrid in wpf? - wpf

I have created search option using combobox, for example
In combobox1 items are m1,m2,m3,m4,m5 based on that, if m1 item selected then
another combobox2 displays with items a,b,c,d and if a item is selected another
combobox3 dispalys, based on last combobox it searches on the datagrid.
I think it is long process, use of many combobox makes it lenghty. Is any
other way is their to implement this. plz help
<ComboBox Grid.Column="1"
Grid.Row="1"
x:Name="cmbType"
VerticalAlignment="Top"
IsEnabled="{Binding IsOther}"
ItemsSource="{Binding Source={StaticResource enumTypeOfType}}"
SelectedItem="{Binding SearchType,Mode=TwoWay}"
SelectedIndex="{Binding CmdResIndex,Mode=TwoWay}"
IsSynchronizedWithCurrentItem="True"
SelectionChanged="DataSource1"
Margin="0,0,1,0">
</ComboBox>

So if i get this right, you have a collection a, which goes to collection b,etc, and the second collection will change based on the selected item of the first? You have to remember, that since the data will change for each selection, hard coding the value is out of the question.
Knowing this, WPF provides you with a great mechanism for this. Using a stackpanel, with a list view will actually work.
<ItemsControl ItemsSource="{binding collections}" ItemTemplate="{binding TemplateForListViewItems}" ItemPanelTemplate="{binding itemPanelTemplate}"></ItemsControl>
Now, with the items control, one can simply set an ItemTemplate/DataTemplate, to set the styling of each control. Linking to the onclick event, or using interactions, you can simply do collections.Add to add your new list view with generated data for the selection, and done.

Related

WPF cascading ComboBoxes not binding when window loads

I'm using WPF and MVVM, and have a support ticket window that has cascading ComboBoxes as follows. The first is bound to an ObservableCollection<ProblemCode> on the view model. The ProblemCode objects have a self-referencing property to their child codes, down to a level of four codes. The XAML for the ComboBoxes looks like this (simplified, and only three shown for brevity)...
<ComboBox ItemsSource="{Binding ElementName=Root, Path=DataContext.ProblemCodes, Mode=TwoWay}"
Name="ProblemCodeLevel1"
DisplayMemberPath="Description"
SelectedValuePath="ID"
SelectedValue="{Binding ProblemCode1ID, Mode=TwoWay}" />
<ComboBox ItemsSource="{Binding ElementName=ProblemCodeLevel1, Path=SelectedItem.Children}"
Name="ProblemCodeLevel2"
DisplayMemberPath="Description"
SelectedValuePath="ID"
SelectedValue="{Binding ProblemCode2ID, Mode=TwoWay}" />
<ComboBox ItemsSource="{Binding ElementName=ProblemCodeLevel2, Path=SelectedItem.Children}"
Name="ProblemCodeLevel3"
DisplayMemberPath="Description"
SelectedValuePath="ID"
SelectedValue="{Binding ProblemCode3ID, Mode=TwoWay}" />
When I load a window for a new ticket, the first ComboBox is correctly populated. Selecting an item populates the second and so on. When I save the ticket, the data is correctly saved.
However, when I save the ticket and reopen the window, only the first ComboBox has the selected item set. The other ComboBoxes don't have anything set.
I guess that the first ComboBox is set as the data is available when the data binding takes place. At that stage, as the first ComboBox is data bound, the second one doesn't yet have any items, so doesn't get bound. Same for the third and so on.
Anyone any suggestions as to how to get the binding working? I probably could hack this by adding code to catch various events, but apart from breaking the MVVM pattern, it sounds like none of those situations that would end up convoluted and buggy.
Generally speaking you shouldn't bind directly to elements, you should be binding to properties in your view model. That way you know the property notification is being done properly and you can add breakpoints etc to confirm the bindings are all working as well. In this particular case you need to add something like SelectedItem="{Binding Level1Item}" to your first ComboBox and then add a property for it in your view model:
public ProblemCode _Level1Item;
public ProblemCode Level1Item
{
get { return this._Level1Item; }
set
{
if (this._Level1Item != value)
{
this._Level1Item = value;
RaisePropertyChanged(() => this.Level1Item);
}
}
}
Then your second ComboBox binds to this property instead of Element.SelectedItem.Children:
<ComboBox ItemsSource="{Binding Level1Item.Children}"
...etc...
Repeat for the second and third ComboBoxes and you'll have the functionality you're after.

Combobox: Get text and selected item in mvvm way

The combobox is editable so user can also write. I have two usecases:
Get the text from combobox in a Lostfocus way, when user writes
something in the box and when he presses "Tab" then I want the text
from the combobox and I add the value in the itemsSource list.
When the users makes the selection from the combobox dropdown, I want that
selected item as soon he selects it and this time I dont
want to have it in Lostfocus manner but somewhat like
PropertyChanged way.
I tried the code which is given below:
<ComboBox Margin="3" x:Name="Combobox" SelectedItem="{Binding SelectedPath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Text="{Binding PathLocation, UpdateSourceTrigger=LostFocus, ValidatesOnNotifyDataErrors=True}" IsTextSearchEnabled="True" VerticalContentAlignment="Center" ItemsSource="{Binding SelectedPaths}" IsEditable="True" Grid.Row="0" Grid.Column="1" Grid.ColumnSpan="2" HorizontalAlignment="Stretch"/>
Things worked fine for the first time when the application starts but after some interactions the problem arises. When the user starts typing in the combobox the SelectedItem property of combobox triggers which is contrary to what I want in the first use case.
In short: when the user writes something in the combobox I want to have it in a Lostfocus manner and when he makes the selection from the dropdown of combobox I want to have it in a PropertyChanged manner.
Let me know if more details are required.
I removed the "IsTextSearchEnabled" property but it also didnt work then I came to know that "IsTextSearchEnabled" property of Comobobox is by default true, which is causing some values suggested by the combobox are setting in my properties. As soon as I made the "IsTextSearchEnabled" to false, it is working fine.

Bind Combobox with huge data in WPF

I am trying to bind combobox with custom object list. My object list have around 15K record and combobox takes long time to show the data after clicking on combobox.
Below are the code:
<ComboBox Height="23" Name="comboBox1" Width="120" DisplayMemberPath="EmpName" SelectedValue="EmpID" VirtualizingStackPanel.IsVirtualizing="True" VirtualizingStackPanel.VirtualizationMode="Recycling"/>
code behind:
List<EmployeeBE> allEmployee = new List<EmployeeBE>();
allEmployee = EmployeeBO.GetEmployeeAll();
comboBox1.ItemsSource = allEmployee;
allEmployee have around 15K record.
Can any one Suggest how can I improve my combobox performance?
That's bad UI design: No user will read through 15K records.
You can improve the performance by allowing the user to enter some filter criteria before showing the results, for example, by using an AutoCompleteBox instead of a ComboBox.
You could try a VirtualizingStackPanel as described here - http://vbcity.com/blogs/xtab/archive/2009/12/15/wpf-using-a-virtualizingstackpanel-to-improve-combobox-performance.aspx
As others have said, you really want to re-imagine your UI, as a ComboBox isn't appropriate for 15k records.
Try using a VirtualizingStackPanel as ItemsPanel for the ComboBox.
<ItemsPanelTemplate x:Key="ComboBoxItemsPanelTemplate">
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
<ComboBox ItemsPanel="{StaticResource ItemsTemplate}"/>

WPF binding to individual 'rows' (not columns) of a datagrid possible?

I have a datagrid. A column of the datagrid is a simple <DataGridTemplateColumn> with its CellTemplate containing a <DataTemplate> which contains a <ComboBox> such as
<my:DataGrid Name="dataGridMain" AutoGenerateColumns="False">
<my:DataGrid.Columns>
<my:DataGridTemplateColumn Header="Food" >
<my:DataGridTemplateColumn.CellTemplate >
<DataTemplate>
<ComboBox Name="comboDataTemplate"
Text="{Binding Path=Food,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}"
ItemsSource="{Binding Source={StaticResource resFoodLookups}}"
DisplayMemberPath="FoodName"
SelectedValuePath="FoodID" IsEditable="True" />
</DataTemplate>
</my:DataGridTemplateColumn.CellTemplate>
</my:DataGridTemplateColumn>
</my:DataGrid.Columns>
</my:DataGrid>
All is working fine. Each combobox is bound to a static list due to the ItemsSource="{Binding Source={StaticResource resFoodLookups}}" statement.
But my requirement is that this list will change from row-to-row.
That is: each time a user types a new entry in the combobox list on one row, I want to have it available in the selection on the next row.
Basically, I want to create a new list for the user each time the user inserts a new word in the combobox on any of the rows. (The combobox is editable).
Now, I can wire up the "ItemsSource=..." at run-time, but I'm only able to do this once thus the <DataTemplate> propagates the 'same' list to 'all' the comboboxes on 'all' the rows.
My thoughts are that I need to change the ItemsSource=... property on an object-by-object basis on each combobox that is created in memory after the DataTemplate has created them - but I have no idea how to do this.
What you need to do is perform 2 way data binding to your the ItemsSource, this way when the ItemSource is updated in one of the combo boxes it will auto update your original collection and therefore your other combo boxes as well.
What I normally do is use the MVVM pattern. It is worth some research if you are not already using a particular pattern on your application.
Using it to solve your problem i would do the following:
Create a ViewModel (Lets call it MyViewModel) which has a collection of values called 'MyComboBoxItems' (It is important that you use ObservableCollection for the databinding to work)
When I create the Window/Control that contains your table, I also create an instance of MyViewModel and set its the Window.DataContext=myViewModelInstance
For your combobox binding use ItemsSource="{Binding Path=MyComboBoxItems, Mode=TwoWay}

WPF: Can I bind to a method of the selected object in another control?

I have two WPF list boxes. One is a list of lists (actually a List of ObservableCollection), the other is a list of all known instances of "Thingy".
Here's the datatemplate I'm using for the "thingy" class.
<DataTemplate DataType="{x:Type Model:Thingy}">
<StackPanel Orientation="Horizontal">
<CheckBox x:Name="ThingyInListCheckBox" Click="ThingyInList_Click"></CheckBox>
<TextBlock Text="{Binding Path=ThingyName}"></TextBlock>
</StackPanel>
Here's the XAML for the list boxes:
<ListBox
Name="ListOfGroups"
SelectionMode="Single">
</ListBox>
<ListBox
Name="ListOfThingys"
SelectionMode="Single">
</ListBox>
I have the data binding for the list boxes set up in code, because I'm too tired to figure out how to do it in XAML:
ListOfGroups.ItemsSource = InMemoryCache.ThingyGroups;
ListOfThingys.ItemsSource = InMemoryCache.Thingys;
What I want is the checkbox "ThingyInListCheckBox" to be checked if the 'thingy' object is in the list that is the selected item in the "ListOfGroups" listbox. So basically I need to bind it to the "Contains" method of the "ListOfGroups".SelectedItem while passing it the "ListOfThingys".SelectedItem as a parameter.
I'm tempted to do this all in code, but I'm trying to get a better understanding of XAML data binding because I hate myself and I want me to suffer.
Is this even possible, or have I hit the inevitable "wall of databinding" that exists in every other data binding system in the history of software development?
It is possible, in fact the hard thing is that there are many ways to do this and you have to choose one. None of them is a simple addition to your current code. However there is one way, by which you gain more than solving your problem. Actually, it is more of a pattern, called MVVM (some might argue about the naming).
Here is a small explanation on your example.
Suppose ThingyGroup has an IsSelected property, which is bound to the IsSelected property of the containing ListBoxItem. Again, suppose Thingy has a Group property too. Then you can use Group.IsSelected as a path to bind checkbox. Notice that there is still a small issue that IsSelected is a bool and IsChecked is a nullable bool.
A search on MVVM should give you concrete samples.

Resources