Scroll multiple virtualized itemcontrols












2















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]










share|improve this question

























  • 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
















2















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]










share|improve this question

























  • 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














2












2








2








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]










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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



















  • 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

















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












2 Answers
2






active

oldest

votes


















0














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.






share|improve this answer
























  • 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



















0














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.






share|improve this answer

























    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
    });


    }
    });














    draft saved

    draft discarded


















    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









    0














    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.






    share|improve this answer
























    • 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
















    0














    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.






    share|improve this answer
























    • 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














    0












    0








    0







    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.






    share|improve this answer













    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.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    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



















    • 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













    0














    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.






    share|improve this answer






























      0














      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.






      share|improve this answer




























        0












        0








        0







        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.






        share|improve this answer















        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.







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 19 '18 at 10:19

























        answered Nov 16 '18 at 15:04









        ITCBBITCBB

        1114




        1114






























            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            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





















































            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







            Popular posts from this blog

            Florida Star v. B. J. F.

            Danny Elfman

            Lugert, Oklahoma