WPF ComboBox Large Data Source MVVM - c#

I have this combobox which is bound to a list of customers with around 5k entries
<ComboBox ItemsSource="{Binding Customers}" Margin="0 0 0 18"
DisplayMemberPath="DisplayMember"
SelectedValuePath="Id"
SelectedValue="{Binding CustomerId,Mode=OneWay}"
>
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
I changed to virtualization and this helped in getting the list faster but when I added SelectedValue to bind to my viewmodel it got very very slow to load.
Is there any way to overcome this problem ?
Regards

5000 entries in a combobox is quite a burden on the system.
It is also a burden on a user. In general a combobox should not contain more than 10 (debatable) items.
In general I would make the user (or the system) do a pre-selection by adding a filter which decides what items should show in the combobox E.g., all names starting with "A" or, if that set is still too large, all names starting with "Ande".

Related

Problem with multiple ListBox binding same SelectedItem property

I have a screen in WPF that needs to list data from same database table, but separately by status. In the print each column is a different status and each is a ListBox, the SelectedItem binding for all ListBox is the same property in ViewModel. The problem is when an item is selected in some ListBox it still selected even after I select an item from other ListBox and when the focus return to the first ListBox (with Tab key for example) the item gets the selected style. Any idea how to resolve this? I can change the ListBoxes for other solution too, at this moment i can't see other solution.
Sorry for my bad English, and I don't know if the explanation is much clear this feature is a bit complicated to explain, but any doubts I'll provide the answers.
Thanks for all.
do you want to have the same item selected in each listbox? Try adding IsSynchronizedWithCurrentItem="true" to every listbox in xaml:
<StackPanel>
<!--both comboboxes are synchronized with each other-->
<ComboBox ItemsSource="{Binding Products}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name"/>
<ComboBox ItemsSource="{Binding Products}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name"/>
</StackPanel>

c# uwp virtualization issue

I have a grid view that is populated with lot of items...each item has a Image in it. And when user scrolls down, some items become unrealized by virtualization. And, when user scrolls back to show them, those items start to update data, image source. The problem is that updating image source blocks the UI, and items in my grid are not showing until the image is loaded. This looks bad, and very choppy scrolling...
Here is the example what virtualization is doing in gridview:
My question is, how to set number of items that virtualization will make realized?
Use the CacheLength property of the virtualizing panel.
<ListView>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel CacheLength="0" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
</ListView>
If cache length is in multiples of view port size. So if 3 items are visible in the window and cache length is 1, then you'll have 3 realized items before and 3 realized items after, (3+3+3 = 9). If cache length is 2, then 6+6+3 = 15, etc.
This works with GridView as well:
<GridView>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid CacheLength="0" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>

Stop ComboBox from scrolling to top

In WPF, is there any way to disable the scroll behavior of the ComboBox that auto-scrolls to the top of the list whenever a user reaches the end of the list? I'd rather that the list stayed at the end and the user have to manually scroll back to the top.
Heres the XAML for the ComboBox:
<ComboBox x:Name="CellProviderCombo" HorizontalAlignment="Left" Height="65" Margin="14,405,0,0" VerticalAlignment="Top" Width=" 327" Header="Cell Provider" PlaceholderText="Choose Cell Provider" DataContext="{StaticResource GlobalVars}" ItemsSource="{Binding GlobalShopInfo.CellProviders}" DisplayMemberPath="Name" SelectedValuePath="Name" IsDoubleTapEnabled="False"/>
As I said, if you scroll past the last element in the combobox it simply starts over at the bottom and the scroll bar shoots back up to the top automatically.
Turns out that the ComboBox in WPF is not the same ComboBox used in Windows Apps Windows.UI.Xaml.
The ComboBox used in Windows Apps uses a Carousel instead of a StackPanel to display its items. One of the effects this has is making it so when you reach the end of the list, it simply loops back to the top. The solution is to manually change the ItemsPanelTemplate to a StackPanel as follows:
<ComboBox x:Name="MyComboBox"> //Add other properties in this line as well if needed
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
Hope this helps anyone who has a similar issue.

Select ListView item when combobox/textbox is selected WPF MVVM

I have a ListView which contains a collection of objects as itemssource and the selected object as SelectedItem.
<ListView Margin="5 0 5 0" ItemsSource="{Binding ObjectCollection}" SelectedItem="{
Binding SelectedObject}" Grid.Row="1">
Inside the ListView.View I have several GridViewColumns which each have a CellTemplate
<GridViewColumn CellTemplate="{StaticResource ReferenceToCellTemplate}" Header="{
Binding ColumnName, Converter={StaticResource upperConverter}}" Width="90"
HeaderContainerStyle="{StaticResource StaticGridViewColumnHeaderStyleWhite}"/>
An example of such a template:
<DataTemplate x:Key="ReferenceToCellTemplate">
<ComboBox ItemsSource="{Binding PossibleValuesForProperty, UpdateSourceTrigger=
PropertyChanged}" SelectedItem="{Binding SelectedProperty, UpdateSourceTrigger=
PropertyChanged}" SelectionChanged="Protocol_ComboBox_SelectionChanged"/>
</DataTemplate>
Now for the issue:
Say that I have 2 comboboxes in this listview. for example a combobox with different software and another with the different versions of this software.
Whenever the software has changed in a certain row, the possible versions should be updated.
The question:
How do I know which object the software combobox belongs too so that I can adjust the possible versions for this object?
When you change the value inside the combobox, this doesn't mean that the row is selected. So when I try to adjust the versions along with the selected row, I might as well be adjust the wrong row.
So the way I see it there are 2 possibilities:
Select the given row whenever something inside that row is adjusted/selected
Get to know which row the changed/selected control is in without selecting it
Any help would be much appreciated.
The solution is to not use an event handler for when the property is changed but just to handle the change in the properties for the row object. So when the property for "software" changes, call a method which adjust the "PossibleVersions" property for this software. All of this inside the VM for the row object.
Basic beginner MVVM mistake I guess

WP7 : access and change controls inside a ListBox DataTemplate based on the data from the database

I know this has been asked before but Im a bit confused !
I'm writing my app with MVVM so far so good. but now I need to know what is the best way to access my controls inside a data template in a listbox.
I want to access them through the code behind and also be able to change them based on the other values from the database !
Here is the view :
<ListBox Margin="0,8,0,0" toolkit:TiltEffect.IsTiltEnabled="True" x:Name="counterlist" ItemsSource="{Binding Groups}" HorizontalAlignment="Center" Tap="list_OnTap"
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Background="Orange" Width="125" Height="125" Margin="6">
<TextBlock Name="name" Foreground="White" Text="{Binding Name}" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap"/>
<TextBlock Name="items" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" TextAlignment="Center" TextWrapping="Wrap"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<toolkit:WrapPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
This list box is bound to the Groups Observable collection in my viewModel. Again so far so good.
Now I have a method called
public int ItemsinGroup(int gid)
This method returns number of items in each group but its not simply based on this database and it also get some info from an external source so I cant simply make a query to add this also to the observable collection.
I just need to add this to each item in the list box so that it shows the associated item counts for each group.
I want to be able to change it in the code behind. I mean I want to access each loop of data in code behind as well as XAML (Which we are already doing it through binding) .
If I can do so it will be easy to inject ItemsinGroup results to its related item in the list box loop.
Can I do that by placing my method in viewModel ? but what about the current item in the loop, how can I find out what is the current ID of each Group in the listbox loop ?
I need to know what is the best way to do such things, what usually everyone does in these cases !
Thanks a lot
Your desire to use MVVM and yet update individual items in a collection from code behind seem contradictory.
This simplest solution is probably to get your collection of groups and before you bind them to the UI you loop through them and add the count to the objects in your collection.
Alternatively, if you want to bind the collection as quickly as possible and then update it. You could step through the collection once bound and as long as the objects in your collection implement INotifyPropertyChanged you could update them and have a second TextBlock in the ItemTemplate show this when set.

Categories

Resources