Scroll multiple virtualized itemcontrols
I've got a calendar-like control with a column for each day of the week and seven ObservableCollections which can contain up to a hundred or more items each.
I'd like to be able to vertically scroll through them [Edit] simultaniously [/Edit] while having them virtualized.
Right now I've got the following layout
<ScrollViewer>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!-- Monday -->
<Border Grid.Column="0">
<ItemsControl ItemsSource="{Binding Monday}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsVirtualizing="True" VirtualizationMode="Recycling" ... />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<MyControl Item="{Binding}" ... />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
...
</Grid>
</ScrollViewer>
However, the performance is questionable and I think it's due to the ScrollViewer allowing the Grid -> Border -> VirtualizingStackPanel to vertically expand and not virtualize at all. Is that the case?
(Sidenote: I've tried to remove the ScrollViewer and add CanVerticallyScroll="True" to the VirtualizingStackPanels and expected them to scroll independently to check if performance is any better but they wouldn't scroll at all)
What could be a correct layout for this?
Edit: Displaying 100 elements for each column (700 total) takes 13 seconds, scrolling is actually okay
[Edit2]:
Due to the required simultanious scrolling, I've tried to create a new collection that contains "one row" (7 items) and that as template in a listview. Horrible results [/Edit2]
c# wpf
|
show 2 more comments
I've got a calendar-like control with a column for each day of the week and seven ObservableCollections which can contain up to a hundred or more items each.
I'd like to be able to vertically scroll through them [Edit] simultaniously [/Edit] while having them virtualized.
Right now I've got the following layout
<ScrollViewer>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!-- Monday -->
<Border Grid.Column="0">
<ItemsControl ItemsSource="{Binding Monday}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsVirtualizing="True" VirtualizationMode="Recycling" ... />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<MyControl Item="{Binding}" ... />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
...
</Grid>
</ScrollViewer>
However, the performance is questionable and I think it's due to the ScrollViewer allowing the Grid -> Border -> VirtualizingStackPanel to vertically expand and not virtualize at all. Is that the case?
(Sidenote: I've tried to remove the ScrollViewer and add CanVerticallyScroll="True" to the VirtualizingStackPanels and expected them to scroll independently to check if performance is any better but they wouldn't scroll at all)
What could be a correct layout for this?
Edit: Displaying 100 elements for each column (700 total) takes 13 seconds, scrolling is actually okay
[Edit2]:
Due to the required simultanious scrolling, I've tried to create a new collection that contains "one row" (7 items) and that as template in a listview. Horrible results [/Edit2]
c# wpf
Hope you have a good reason for using a custom control, usually you can get away withDataTemplate
instead. I think the delay might be due to a complex template, but we can't see that, so this is just a guess.
– XAMlMAX
Nov 15 '18 at 13:05
@XAMlMAX Thanks for your input! Basically because the control might get reused somewhere else. Where might be the benefit to put the content of it in the datatemplate directly?
– ITCBB
Nov 15 '18 at 13:14
Ideally you would have it defined in a resource dictionary as a static resource and then reference it in your xaml where you need it. App.xaml would be a perfect place to start.
– XAMlMAX
Nov 15 '18 at 13:16
I'll check if that would be a possibility, but I've got 540 lines of code behind it.
– ITCBB
Nov 15 '18 at 13:17
Do you meanC#
code or just xaml? And if you have code behind then there is probably a good reason for it, out of curiosity why do you have code behind?
– XAMlMAX
Nov 15 '18 at 13:19
|
show 2 more comments
I've got a calendar-like control with a column for each day of the week and seven ObservableCollections which can contain up to a hundred or more items each.
I'd like to be able to vertically scroll through them [Edit] simultaniously [/Edit] while having them virtualized.
Right now I've got the following layout
<ScrollViewer>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!-- Monday -->
<Border Grid.Column="0">
<ItemsControl ItemsSource="{Binding Monday}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsVirtualizing="True" VirtualizationMode="Recycling" ... />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<MyControl Item="{Binding}" ... />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
...
</Grid>
</ScrollViewer>
However, the performance is questionable and I think it's due to the ScrollViewer allowing the Grid -> Border -> VirtualizingStackPanel to vertically expand and not virtualize at all. Is that the case?
(Sidenote: I've tried to remove the ScrollViewer and add CanVerticallyScroll="True" to the VirtualizingStackPanels and expected them to scroll independently to check if performance is any better but they wouldn't scroll at all)
What could be a correct layout for this?
Edit: Displaying 100 elements for each column (700 total) takes 13 seconds, scrolling is actually okay
[Edit2]:
Due to the required simultanious scrolling, I've tried to create a new collection that contains "one row" (7 items) and that as template in a listview. Horrible results [/Edit2]
c# wpf
I've got a calendar-like control with a column for each day of the week and seven ObservableCollections which can contain up to a hundred or more items each.
I'd like to be able to vertically scroll through them [Edit] simultaniously [/Edit] while having them virtualized.
Right now I've got the following layout
<ScrollViewer>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="1*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<!-- Monday -->
<Border Grid.Column="0">
<ItemsControl ItemsSource="{Binding Monday}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsVirtualizing="True" VirtualizationMode="Recycling" ... />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<MyControl Item="{Binding}" ... />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Border>
...
</Grid>
</ScrollViewer>
However, the performance is questionable and I think it's due to the ScrollViewer allowing the Grid -> Border -> VirtualizingStackPanel to vertically expand and not virtualize at all. Is that the case?
(Sidenote: I've tried to remove the ScrollViewer and add CanVerticallyScroll="True" to the VirtualizingStackPanels and expected them to scroll independently to check if performance is any better but they wouldn't scroll at all)
What could be a correct layout for this?
Edit: Displaying 100 elements for each column (700 total) takes 13 seconds, scrolling is actually okay
[Edit2]:
Due to the required simultanious scrolling, I've tried to create a new collection that contains "one row" (7 items) and that as template in a listview. Horrible results [/Edit2]
c# wpf
c# wpf
edited Nov 15 '18 at 15:20
ITCBB
asked Nov 15 '18 at 12:20
ITCBBITCBB
1114
1114
Hope you have a good reason for using a custom control, usually you can get away withDataTemplate
instead. I think the delay might be due to a complex template, but we can't see that, so this is just a guess.
– XAMlMAX
Nov 15 '18 at 13:05
@XAMlMAX Thanks for your input! Basically because the control might get reused somewhere else. Where might be the benefit to put the content of it in the datatemplate directly?
– ITCBB
Nov 15 '18 at 13:14
Ideally you would have it defined in a resource dictionary as a static resource and then reference it in your xaml where you need it. App.xaml would be a perfect place to start.
– XAMlMAX
Nov 15 '18 at 13:16
I'll check if that would be a possibility, but I've got 540 lines of code behind it.
– ITCBB
Nov 15 '18 at 13:17
Do you meanC#
code or just xaml? And if you have code behind then there is probably a good reason for it, out of curiosity why do you have code behind?
– XAMlMAX
Nov 15 '18 at 13:19
|
show 2 more comments
Hope you have a good reason for using a custom control, usually you can get away withDataTemplate
instead. I think the delay might be due to a complex template, but we can't see that, so this is just a guess.
– XAMlMAX
Nov 15 '18 at 13:05
@XAMlMAX Thanks for your input! Basically because the control might get reused somewhere else. Where might be the benefit to put the content of it in the datatemplate directly?
– ITCBB
Nov 15 '18 at 13:14
Ideally you would have it defined in a resource dictionary as a static resource and then reference it in your xaml where you need it. App.xaml would be a perfect place to start.
– XAMlMAX
Nov 15 '18 at 13:16
I'll check if that would be a possibility, but I've got 540 lines of code behind it.
– ITCBB
Nov 15 '18 at 13:17
Do you meanC#
code or just xaml? And if you have code behind then there is probably a good reason for it, out of curiosity why do you have code behind?
– XAMlMAX
Nov 15 '18 at 13:19
Hope you have a good reason for using a custom control, usually you can get away with
DataTemplate
instead. I think the delay might be due to a complex template, but we can't see that, so this is just a guess.– XAMlMAX
Nov 15 '18 at 13:05
Hope you have a good reason for using a custom control, usually you can get away with
DataTemplate
instead. I think the delay might be due to a complex template, but we can't see that, so this is just a guess.– XAMlMAX
Nov 15 '18 at 13:05
@XAMlMAX Thanks for your input! Basically because the control might get reused somewhere else. Where might be the benefit to put the content of it in the datatemplate directly?
– ITCBB
Nov 15 '18 at 13:14
@XAMlMAX Thanks for your input! Basically because the control might get reused somewhere else. Where might be the benefit to put the content of it in the datatemplate directly?
– ITCBB
Nov 15 '18 at 13:14
Ideally you would have it defined in a resource dictionary as a static resource and then reference it in your xaml where you need it. App.xaml would be a perfect place to start.
– XAMlMAX
Nov 15 '18 at 13:16
Ideally you would have it defined in a resource dictionary as a static resource and then reference it in your xaml where you need it. App.xaml would be a perfect place to start.
– XAMlMAX
Nov 15 '18 at 13:16
I'll check if that would be a possibility, but I've got 540 lines of code behind it.
– ITCBB
Nov 15 '18 at 13:17
I'll check if that would be a possibility, but I've got 540 lines of code behind it.
– ITCBB
Nov 15 '18 at 13:17
Do you mean
C#
code or just xaml? And if you have code behind then there is probably a good reason for it, out of curiosity why do you have code behind?– XAMlMAX
Nov 15 '18 at 13:19
Do you mean
C#
code or just xaml? And if you have code behind then there is probably a good reason for it, out of curiosity why do you have code behind?– XAMlMAX
Nov 15 '18 at 13:19
|
show 2 more comments
2 Answers
2
active
oldest
votes
To make a ItemsControl virtualizing you not only need to use the VirtualizingStackPanel but also add a ScrollViewer to the template of the ItemsControl (normally the ItemsControl does not have a ScrollViewer).
Add this template inside your ItemsControl:
<ItemsControl.Template>
<ControlTemplate>
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
SnapsToDevicePixels="True">
<ScrollViewer Padding="{TemplateBinding Control.Padding}"
Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
As an different solution you can of course replace your ItemsControl with a ListBox, which already has everything needed for virtualizing your list.
Thanks! Where's the VirtualizingStackPanel in this example? And this would result in the columns scroll independently instead of simultaniously, right?
– ITCBB
Nov 15 '18 at 14:13
This is not the entire code only the part you need to add inside your ItemsControl. And yes this will make each column scroll independently.
– Marc
Nov 15 '18 at 14:16
Okay thanks, that sadly is not what I want to achieve, the simultaneous scroll is a must. I guess I could let the others follow but they would just stop at the end while others keep scrolling
– ITCBB
Nov 15 '18 at 14:23
add a comment |
The solution to the issue was to not render the seven columns each with one virtualized ItemsControl in a ScrollViewer (which seemed to expand the ItemsControls and make them draw all controls) but render with one ItemsControl, solving the scrolling through ItemsControl.Template and displaying one row at a time.
I created a new collection and grabbed the objects "per row"
for(int PI = 0; PI < MathHelper.Max(Monday.Count, Tuesday.Count, Wednesday.Count, Thursday.Count, Friday.Count, Saturday.Count, Sunday.Count); PI++)
{
Presentation.Add(new WeekRow(
Monday.Count > PI ? Monday[PI] : null,
Tuesday.Count > PI ? Tuesday[PI] : null,
Wednesday.Count > PI ? Wednesday[PI] : null,
Thursday.Count > PI ? Thursday[PI] : null,
Friday.Count > PI ? Friday[PI] : null,
Saturday.Count > PI ? Saturday[PI] : null,
Sunday.Count > PI ? Sunday[PI] : null
));
}
And displayed them using this
<ItemsControl ItemsSource="{Binding Presentation}" VirtualizingPanel.ScrollUnit="Pixel">
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer CanContentScroll="True" Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel
Orientation="Vertical"
IsVirtualizing="True"
VirtualizationMode="Recycling">
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<MyControl Item="{Binding Monday}" Grid.Column="0" ... />
...
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate
</ItemsControl>
What's really important here, is to set the CanContentScroll-Property of the ScrollViewer to true or otherwise the virtualization will not work (who knows why). This was missing in @Marc's answer.
Edit: What's also worth mentioning is, that to get "smooth scrolling" (well, as "smooth" as wpf can get..), one has to set VirtualizingPanel.ScrollUnit to "Pixel". But it only works when set to the ItemsControl, and not to the ScrollViewer, ItemsPresenter or VirtualizingStackPanel itself. For whatever reason.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53319414%2fscroll-multiple-virtualized-itemcontrols%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
To make a ItemsControl virtualizing you not only need to use the VirtualizingStackPanel but also add a ScrollViewer to the template of the ItemsControl (normally the ItemsControl does not have a ScrollViewer).
Add this template inside your ItemsControl:
<ItemsControl.Template>
<ControlTemplate>
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
SnapsToDevicePixels="True">
<ScrollViewer Padding="{TemplateBinding Control.Padding}"
Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
As an different solution you can of course replace your ItemsControl with a ListBox, which already has everything needed for virtualizing your list.
Thanks! Where's the VirtualizingStackPanel in this example? And this would result in the columns scroll independently instead of simultaniously, right?
– ITCBB
Nov 15 '18 at 14:13
This is not the entire code only the part you need to add inside your ItemsControl. And yes this will make each column scroll independently.
– Marc
Nov 15 '18 at 14:16
Okay thanks, that sadly is not what I want to achieve, the simultaneous scroll is a must. I guess I could let the others follow but they would just stop at the end while others keep scrolling
– ITCBB
Nov 15 '18 at 14:23
add a comment |
To make a ItemsControl virtualizing you not only need to use the VirtualizingStackPanel but also add a ScrollViewer to the template of the ItemsControl (normally the ItemsControl does not have a ScrollViewer).
Add this template inside your ItemsControl:
<ItemsControl.Template>
<ControlTemplate>
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
SnapsToDevicePixels="True">
<ScrollViewer Padding="{TemplateBinding Control.Padding}"
Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
As an different solution you can of course replace your ItemsControl with a ListBox, which already has everything needed for virtualizing your list.
Thanks! Where's the VirtualizingStackPanel in this example? And this would result in the columns scroll independently instead of simultaniously, right?
– ITCBB
Nov 15 '18 at 14:13
This is not the entire code only the part you need to add inside your ItemsControl. And yes this will make each column scroll independently.
– Marc
Nov 15 '18 at 14:16
Okay thanks, that sadly is not what I want to achieve, the simultaneous scroll is a must. I guess I could let the others follow but they would just stop at the end while others keep scrolling
– ITCBB
Nov 15 '18 at 14:23
add a comment |
To make a ItemsControl virtualizing you not only need to use the VirtualizingStackPanel but also add a ScrollViewer to the template of the ItemsControl (normally the ItemsControl does not have a ScrollViewer).
Add this template inside your ItemsControl:
<ItemsControl.Template>
<ControlTemplate>
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
SnapsToDevicePixels="True">
<ScrollViewer Padding="{TemplateBinding Control.Padding}"
Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
As an different solution you can of course replace your ItemsControl with a ListBox, which already has everything needed for virtualizing your list.
To make a ItemsControl virtualizing you not only need to use the VirtualizingStackPanel but also add a ScrollViewer to the template of the ItemsControl (normally the ItemsControl does not have a ScrollViewer).
Add this template inside your ItemsControl:
<ItemsControl.Template>
<ControlTemplate>
<Border BorderThickness="{TemplateBinding Border.BorderThickness}"
Padding="{TemplateBinding Control.Padding}"
BorderBrush="{TemplateBinding Border.BorderBrush}"
Background="{TemplateBinding Panel.Background}"
SnapsToDevicePixels="True">
<ScrollViewer Padding="{TemplateBinding Control.Padding}"
Focusable="False">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
As an different solution you can of course replace your ItemsControl with a ListBox, which already has everything needed for virtualizing your list.
answered Nov 15 '18 at 13:55
MarcMarc
15927
15927
Thanks! Where's the VirtualizingStackPanel in this example? And this would result in the columns scroll independently instead of simultaniously, right?
– ITCBB
Nov 15 '18 at 14:13
This is not the entire code only the part you need to add inside your ItemsControl. And yes this will make each column scroll independently.
– Marc
Nov 15 '18 at 14:16
Okay thanks, that sadly is not what I want to achieve, the simultaneous scroll is a must. I guess I could let the others follow but they would just stop at the end while others keep scrolling
– ITCBB
Nov 15 '18 at 14:23
add a comment |
Thanks! Where's the VirtualizingStackPanel in this example? And this would result in the columns scroll independently instead of simultaniously, right?
– ITCBB
Nov 15 '18 at 14:13
This is not the entire code only the part you need to add inside your ItemsControl. And yes this will make each column scroll independently.
– Marc
Nov 15 '18 at 14:16
Okay thanks, that sadly is not what I want to achieve, the simultaneous scroll is a must. I guess I could let the others follow but they would just stop at the end while others keep scrolling
– ITCBB
Nov 15 '18 at 14:23
Thanks! Where's the VirtualizingStackPanel in this example? And this would result in the columns scroll independently instead of simultaniously, right?
– ITCBB
Nov 15 '18 at 14:13
Thanks! Where's the VirtualizingStackPanel in this example? And this would result in the columns scroll independently instead of simultaniously, right?
– ITCBB
Nov 15 '18 at 14:13
This is not the entire code only the part you need to add inside your ItemsControl. And yes this will make each column scroll independently.
– Marc
Nov 15 '18 at 14:16
This is not the entire code only the part you need to add inside your ItemsControl. And yes this will make each column scroll independently.
– Marc
Nov 15 '18 at 14:16
Okay thanks, that sadly is not what I want to achieve, the simultaneous scroll is a must. I guess I could let the others follow but they would just stop at the end while others keep scrolling
– ITCBB
Nov 15 '18 at 14:23
Okay thanks, that sadly is not what I want to achieve, the simultaneous scroll is a must. I guess I could let the others follow but they would just stop at the end while others keep scrolling
– ITCBB
Nov 15 '18 at 14:23
add a comment |
The solution to the issue was to not render the seven columns each with one virtualized ItemsControl in a ScrollViewer (which seemed to expand the ItemsControls and make them draw all controls) but render with one ItemsControl, solving the scrolling through ItemsControl.Template and displaying one row at a time.
I created a new collection and grabbed the objects "per row"
for(int PI = 0; PI < MathHelper.Max(Monday.Count, Tuesday.Count, Wednesday.Count, Thursday.Count, Friday.Count, Saturday.Count, Sunday.Count); PI++)
{
Presentation.Add(new WeekRow(
Monday.Count > PI ? Monday[PI] : null,
Tuesday.Count > PI ? Tuesday[PI] : null,
Wednesday.Count > PI ? Wednesday[PI] : null,
Thursday.Count > PI ? Thursday[PI] : null,
Friday.Count > PI ? Friday[PI] : null,
Saturday.Count > PI ? Saturday[PI] : null,
Sunday.Count > PI ? Sunday[PI] : null
));
}
And displayed them using this
<ItemsControl ItemsSource="{Binding Presentation}" VirtualizingPanel.ScrollUnit="Pixel">
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer CanContentScroll="True" Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel
Orientation="Vertical"
IsVirtualizing="True"
VirtualizationMode="Recycling">
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<MyControl Item="{Binding Monday}" Grid.Column="0" ... />
...
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate
</ItemsControl>
What's really important here, is to set the CanContentScroll-Property of the ScrollViewer to true or otherwise the virtualization will not work (who knows why). This was missing in @Marc's answer.
Edit: What's also worth mentioning is, that to get "smooth scrolling" (well, as "smooth" as wpf can get..), one has to set VirtualizingPanel.ScrollUnit to "Pixel". But it only works when set to the ItemsControl, and not to the ScrollViewer, ItemsPresenter or VirtualizingStackPanel itself. For whatever reason.
add a comment |
The solution to the issue was to not render the seven columns each with one virtualized ItemsControl in a ScrollViewer (which seemed to expand the ItemsControls and make them draw all controls) but render with one ItemsControl, solving the scrolling through ItemsControl.Template and displaying one row at a time.
I created a new collection and grabbed the objects "per row"
for(int PI = 0; PI < MathHelper.Max(Monday.Count, Tuesday.Count, Wednesday.Count, Thursday.Count, Friday.Count, Saturday.Count, Sunday.Count); PI++)
{
Presentation.Add(new WeekRow(
Monday.Count > PI ? Monday[PI] : null,
Tuesday.Count > PI ? Tuesday[PI] : null,
Wednesday.Count > PI ? Wednesday[PI] : null,
Thursday.Count > PI ? Thursday[PI] : null,
Friday.Count > PI ? Friday[PI] : null,
Saturday.Count > PI ? Saturday[PI] : null,
Sunday.Count > PI ? Sunday[PI] : null
));
}
And displayed them using this
<ItemsControl ItemsSource="{Binding Presentation}" VirtualizingPanel.ScrollUnit="Pixel">
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer CanContentScroll="True" Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel
Orientation="Vertical"
IsVirtualizing="True"
VirtualizationMode="Recycling">
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<MyControl Item="{Binding Monday}" Grid.Column="0" ... />
...
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate
</ItemsControl>
What's really important here, is to set the CanContentScroll-Property of the ScrollViewer to true or otherwise the virtualization will not work (who knows why). This was missing in @Marc's answer.
Edit: What's also worth mentioning is, that to get "smooth scrolling" (well, as "smooth" as wpf can get..), one has to set VirtualizingPanel.ScrollUnit to "Pixel". But it only works when set to the ItemsControl, and not to the ScrollViewer, ItemsPresenter or VirtualizingStackPanel itself. For whatever reason.
add a comment |
The solution to the issue was to not render the seven columns each with one virtualized ItemsControl in a ScrollViewer (which seemed to expand the ItemsControls and make them draw all controls) but render with one ItemsControl, solving the scrolling through ItemsControl.Template and displaying one row at a time.
I created a new collection and grabbed the objects "per row"
for(int PI = 0; PI < MathHelper.Max(Monday.Count, Tuesday.Count, Wednesday.Count, Thursday.Count, Friday.Count, Saturday.Count, Sunday.Count); PI++)
{
Presentation.Add(new WeekRow(
Monday.Count > PI ? Monday[PI] : null,
Tuesday.Count > PI ? Tuesday[PI] : null,
Wednesday.Count > PI ? Wednesday[PI] : null,
Thursday.Count > PI ? Thursday[PI] : null,
Friday.Count > PI ? Friday[PI] : null,
Saturday.Count > PI ? Saturday[PI] : null,
Sunday.Count > PI ? Sunday[PI] : null
));
}
And displayed them using this
<ItemsControl ItemsSource="{Binding Presentation}" VirtualizingPanel.ScrollUnit="Pixel">
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer CanContentScroll="True" Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel
Orientation="Vertical"
IsVirtualizing="True"
VirtualizationMode="Recycling">
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<MyControl Item="{Binding Monday}" Grid.Column="0" ... />
...
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate
</ItemsControl>
What's really important here, is to set the CanContentScroll-Property of the ScrollViewer to true or otherwise the virtualization will not work (who knows why). This was missing in @Marc's answer.
Edit: What's also worth mentioning is, that to get "smooth scrolling" (well, as "smooth" as wpf can get..), one has to set VirtualizingPanel.ScrollUnit to "Pixel". But it only works when set to the ItemsControl, and not to the ScrollViewer, ItemsPresenter or VirtualizingStackPanel itself. For whatever reason.
The solution to the issue was to not render the seven columns each with one virtualized ItemsControl in a ScrollViewer (which seemed to expand the ItemsControls and make them draw all controls) but render with one ItemsControl, solving the scrolling through ItemsControl.Template and displaying one row at a time.
I created a new collection and grabbed the objects "per row"
for(int PI = 0; PI < MathHelper.Max(Monday.Count, Tuesday.Count, Wednesday.Count, Thursday.Count, Friday.Count, Saturday.Count, Sunday.Count); PI++)
{
Presentation.Add(new WeekRow(
Monday.Count > PI ? Monday[PI] : null,
Tuesday.Count > PI ? Tuesday[PI] : null,
Wednesday.Count > PI ? Wednesday[PI] : null,
Thursday.Count > PI ? Thursday[PI] : null,
Friday.Count > PI ? Friday[PI] : null,
Saturday.Count > PI ? Saturday[PI] : null,
Sunday.Count > PI ? Sunday[PI] : null
));
}
And displayed them using this
<ItemsControl ItemsSource="{Binding Presentation}" VirtualizingPanel.ScrollUnit="Pixel">
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer CanContentScroll="True" Focusable="False">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel
Orientation="Vertical"
IsVirtualizing="True"
VirtualizationMode="Recycling">
</VirtualizingStackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<MyControl Item="{Binding Monday}" Grid.Column="0" ... />
...
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate
</ItemsControl>
What's really important here, is to set the CanContentScroll-Property of the ScrollViewer to true or otherwise the virtualization will not work (who knows why). This was missing in @Marc's answer.
Edit: What's also worth mentioning is, that to get "smooth scrolling" (well, as "smooth" as wpf can get..), one has to set VirtualizingPanel.ScrollUnit to "Pixel". But it only works when set to the ItemsControl, and not to the ScrollViewer, ItemsPresenter or VirtualizingStackPanel itself. For whatever reason.
edited Nov 19 '18 at 10:19
answered Nov 16 '18 at 15:04
ITCBBITCBB
1114
1114
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53319414%2fscroll-multiple-virtualized-itemcontrols%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Hope you have a good reason for using a custom control, usually you can get away with
DataTemplate
instead. I think the delay might be due to a complex template, but we can't see that, so this is just a guess.– XAMlMAX
Nov 15 '18 at 13:05
@XAMlMAX Thanks for your input! Basically because the control might get reused somewhere else. Where might be the benefit to put the content of it in the datatemplate directly?
– ITCBB
Nov 15 '18 at 13:14
Ideally you would have it defined in a resource dictionary as a static resource and then reference it in your xaml where you need it. App.xaml would be a perfect place to start.
– XAMlMAX
Nov 15 '18 at 13:16
I'll check if that would be a possibility, but I've got 540 lines of code behind it.
– ITCBB
Nov 15 '18 at 13:17
Do you mean
C#
code or just xaml? And if you have code behind then there is probably a good reason for it, out of curiosity why do you have code behind?– XAMlMAX
Nov 15 '18 at 13:19