My MVVM WPF application uses Linq2SQL for using SQL Server Express. I noticed after populating the database with real data I get some big delays for the UI to update and thought is was my query/ grouping strategy. But, while some of the data fills take more than 100ms, rarely do they take more than 200ms but I'm seeing a lag of up to 3 seconds on the window refresh. EDIT FOR BREVITY:
I was wrapping my ItemsControl in a ScrollViewer:
<ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2" ScrollChanged="ScrollViewer_ScrollChanged">
<ItemsControl x:Name="DivisionItems" ItemsSource="{Binding oObsByDiv}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<uc:ucObservationsHeader/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
But after some hints from below and reading up on Virtualization I now use a ListBox like so:
<ListBox x:Name="DivisionItems" Grid.Column="0" Grid.Row="3" Grid.ColumnSpan="2"
ItemsSource="{Binding oObsByDiv}"
ScrollViewer.CanContentScroll="True"
VirtualizingStackPanel.ScrollUnit="Pixel">
<ListBox.Template>
<ControlTemplate>
<ScrollViewer VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<uc:ucObservationsHeader/>
</DataTemplate>
</ListBox.ItemTemplate>
The user control used for the Items in that template then calls another user control that I'm wrapping in another ListBox in a very similar manner:
<ListBox ItemsSource="{Binding lObs}" Grid.Row="1" Grid.Column="1"
HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.CanContentScroll="True"
VirtualizingStackPanel.ScrollUnit="Pixel">
<ListBox.Template>
<ControlTemplate>
<ScrollViewer VirtualizingStackPanel.IsVirtualizing="True"
VirtualizingStackPanel.VirtualizationMode="Recycling">
<ItemsPresenter/>
</ScrollViewer>
</ControlTemplate>
</ListBox.Template>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemTemplate>
<DataTemplate>
<uc:ucObservationsView/>
</DataTemplate>
</ListBox.ItemTemplate>
But the multiple second lag still exists. The outer user control is instantiated 15 times, and the inner one has on average 15 items each. What is it that is breaking virtualization in this case? I keep stripping out the ScrollUnit and CanContentScroll in one or both places, as well as the HorizontalContentAlignement and the HorizontalScrollBar visibility, but those just affect the look without seeming to be the cause for breaking virtualization.
My ListBox currently binds as expected using
<ListBox ItemsSource="{Binding ChildDuplicate, UpdateSourceTrigger=PropertyChanged}" DataContext="{Binding}" Height="Auto" >
Where ChildDuplicate is an ObservableCollection<MyUserControl>
The problem I am facing is I need to add a button for every item within the ListBox (so it shows both my MyUserControl and the Button control).
This button cannot live within the MyUserControl for several reasons.
I was hoping to use a DataTemplate but this doesn't seem to work (XmlParser error is thrown), I've tried
<ListBox ItemsSource="{Binding ChildDuplicate, UpdateSourceTrigger=PropertyChanged}" DataContext="{Binding}" Height="Auto" >
<ListBoxItem>
<DataTemplate>
<ContentControl Content="{Binding}"></ContentControl>
</DataTemplate>
</ListBoxItem>
</ListBox>
I also tried using the ItemsControl control in the same way, the same issue.
Any idea how I use the DataTemplate to display the content in the exactly same way as not using a DataTemplate?
Try this instead:
<ListBoxItem>
<ListBoxItem.Template>
<ControlTemplate>
<ContentControl Content="{Binding}"></ContentControl>
</ControlTemplate>
</ListBoxItem.Template>
</ListBoxItem>
I've got following code. Why are my items always clipped after about 70px
<sdk:HierarchicalDataTemplate x:Key="OptionsTemplate">
<CheckBox IsTabStop="False" Content="{Binding EnumValue}" IsChecked="{Binding IsSelected, Mode=TwoWay}" />
</sdk:HierarchicalDataTemplate>
<sdk:HierarchicalDataTemplate x:Key="EnumOptionsTemplate" ItemsSource="{Binding Values}" ItemTemplate="{StaticResource OptionsTemplate}">
<TextBlock Text="{Binding EnumType}"/>
</sdk:HierarchicalDataTemplate>
<sdk:TreeView x:Name="FilterTreeView" ItemsSource="{Binding GeoObjectFilter}" ItemTemplate="{StaticResource EnumOptionsTemplate}">
<sdk:TreeView.Template>
<ControlTemplate TargetType="sdk:TreeView">
<StackPanel Background="Transparent">
<ItemsPresenter x:Name="TreeItems" />
</StackPanel>
</ControlTemplate>
</sdk:TreeView.Template>
</sdk:TreeView>
Thanks in advance!
Ho yes i had same issue when redefining the TreeView Template. By the way, i'm not sure you need to, since StackPanel is the Default Template. I got my (wrappanel) template to work by setting a style for ItemsPanel rather than redifining it. And i had to define some width also. Seems the only way to make the Treeview to scale is to bind the width.
See the answer i made to my question here :
https://stackoverflow.com/a/8802718/856501
I have a listBox and add data to it like so:
for (int x = 0; x < Orchestrator.Instance.getTopicCount(); x++)
{
listTopics.Items.Add(Orchestrator.Instance.getTopic(x));
}
But I need to be able to do things like have text wrapping and divider lines, so I would like to do it the XAML.
Microsoft shows this:
<TextBlock Width="248" Height="24"
Text="{Binding ElementName=lbColor, Path=SelectedItem.Content,
Mode=OneWay}"
x:Name="tbSelectedColor"
Background="{Binding ElementName=lbColor, Path=SelectedItem.Content,
Mode=OneWay}"/>
But I don't really understand it. Here is my XAML:
<ListBox Height="261" HorizontalAlignment="Left" Margin="352,38,0,0" Name="listContent" VerticalAlignment="Top" Width="391" Grid.Column="1" HorizontalContentAlignment="Left" VerticalContentAlignment="Center" MaxWidth="391" ScrollViewer.HorizontalScrollBarVisibility="Disabled"/>
How am I able to achieve what I want? (Divider lines, text wrapping so I don't have to scroll horizontally, and data binding)
To specify the layout of each item, there are two different things you can change: the ItemContainerStyle, which provides the ControlTemplate used for each ListBoxItem, or the ItemTemplate, which provides the DataTemplate that is used to render each data item. The ItemTemplate is simpler to use if you're just getting started and haven't gotten the hang of ControlTemplates yet.
To get your text to wrap, there are two key things to do. Turn off the default horizontal scrolling of ListBox (which you got already), and set the TextWrapping property of your TextBlock to Wrap. To get to the TextBlock you need to define it in your ItemTemplate. Here's a simple example of the template declared inline, though you could also pull it out as a Resource. For the dividing line I used the simplest approach of a Border with only a bottom black line.
<ListBox x:Name="listContent" ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderThickness="0,0,0,1" BorderBrush="Black">
<TextBlock Text="{Binding}" TextWrapping="Wrap"/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
It seems that you will have to ascend the rather steep learning curve for how to use databinding in WPF first. Thereafter you should learn about DataTemplates and ItemTemplates to get the dividers and so forth.
Try this to get you started
A book I can heartily recommend is WPF in Action from Manning.
You need to define the ItemTemplate of your ListBox.
In your resources, add this:
<DataTemplate x:Key="myItemTemplate" TargetType="ListBoxItem">
<TextBlock Text="{Binding}"/>
</DataTemplate>
Supposing that your getTopic method returns a string, otherwise use {Binding MyTopicProperty} where MyTopicProperty is a property in your Topic class. Customize the TextBlock as you need.
Then use your ListBox like this:
<ListBox ItemTemplate="{StaticResource myItemTemplate"/>
here is an example how to bind listbox with RSS feed with DataTemplate:
<UserControl.Resources>
<XmlDataProvider x:Key ="DataRSS" XPath="//item" Source="http://rss.feedsportal.com/c/629/f/502199/index.rss">< /XmlDataProvider>
</UserControl.Resources>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<ListBox ItemsSource="{Binding Source={StaticResource DataRSS}}" Height="516" Margin="0,0,32,0" Background="{x:Null}" BorderBrush="#FF627DAE">
<ListBox.ItemTemplate >
<DataTemplate >
<Grid Width="400" Height="100" >
<Image Source="{Binding XPath=enclosure/#url}" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Top" />
<TextBlock TextWrapping="Wrap" Text="{Binding XPath=title}" FontWeight="Bold" Grid.Column="2"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</grid>
How to separate between items BY Lines in ListView control in WPF ?
You can change the ItemTemplate for the ListBox,
given the little information you have provided, just a quick example:
<ListBox>
<ListBox.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="0.5">
<TextBlock Text={Binding}/>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
You will have to modify it to suit your needs.