Load large data set with WPF ContextMenu for RichTextBox - wpf

I'm into a situation where the number of items of a ContextMenu has gone to a number like 3 thousand. In this scenario, the ContextMenu takes lot of time in loading itself. I'm trying to do UI Virtualization but without any luck.
The sample code is as follows:
<RichTextBox x:Name="FMWpfPopupControlHost" ScrollViewer.CanContentScroll="True" VirtualizingStackPanel.IsVirtualizing="True" HorizontalAlignment="Left" Width="300" Height="600" Focusable="True" Loaded="onLoaded1">
<RichTextBox.ContextMenu >
<ContextMenu VirtualizingStackPanel.IsVirtualizing="True" ItemsSource="{Binding GetLabel, Source ={StaticResource model}}" ScrollViewer.CanContentScroll="True">
<ContextMenu.ItemTemplate>
<DataTemplate>
<TextBlock Initialized="TextBlock_Initialized" Text="{Binding getLabel}"/>
</DataTemplate>
</ContextMenu.ItemTemplate>
<ContextMenu.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" IsVirtualizing="True" VirtualizationMode="Recycling"/>
</ItemsPanelTemplate>
</ContextMenu.ItemsPanel>
<ContextMenu.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>
</ContextMenu.Template>
</ContextMenu>
</RichTextBox.ContextMenu>
</RichTextBox>
Please guide me how can I resolve this issue?
Thanks!
Harsh Gupta

Related

How to make Items in ItemsControl scrollable? [duplicate]

I followed this small "tutorial" on how to add a scrollbar to an ItemsControl, and it works in Designer view, but not when I compile and execute the program (only the first few items show up, and no scrollbar to view more - even when VerticalScrollbarVisibility is set to "Visible" instead of "Auto").
Any idea on how to solve this?
This is the code I use to show my items (normally I work with Databinding, but to see the items in my Designer I added them manually):
<ItemsControl x:Name="itemCtrl" Style="{DynamicResource UsersControlStyle}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Top">
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<uc:UcSpeler />
<uc:UcSpeler />
<uc:UcSpeler />
<uc:UcSpeler />
<uc:UcSpeler />
</ItemsControl>
And this is my Template:
<Style x:Key="UsersControlStyle" TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border SnapsToDevicePixels="true" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="{TemplateBinding Padding}">
<ScrollViewer VerticalScrollBarVisibility="Visible">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
To get a scrollbar for an ItemsControl, you can host it in a ScrollViewer like this:
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsControl>
<uc:UcSpeler />
<uc:UcSpeler />
<uc:UcSpeler />
<uc:UcSpeler />
<uc:UcSpeler />
</ItemsControl>
</ScrollViewer>
You have to modify the control template instead of ItemsPanelTemplate:
<ItemsControl >
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer x:Name="ScrollViewer" Padding="{TemplateBinding Padding}">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
Maybe, your code does not working because StackPanel has own scrolling functionality. Try to use StackPanel.CanVerticallyScroll property.
Put your ScrollViewer in a DockPanel and set the DockPanel MaxHeight property
[...]
<DockPanel MaxHeight="700">
<ScrollViewer VerticalScrollBarVisibility="Auto">
<ItemsControl ItemSource ="{Binding ...}">
[...]
</ItemsControl>
</ScrollViewer>
</DockPanel>
[...]

WPF Disable mousewheel on ScrollViewer and let children handle it

I am trying to implement an ItemsControl which contains a collection of graphing components. The component should be able to use the MouseWheel event to zoom, but it appears that the Scrollbar is capturing and handling the event first. Most of the articles I have found here and here speak to letting parents handle the wheel, but I need the child to handle the wheel, and I can't figure out the right hooks. Here is my TiledGrid, which is an ItemsControl at its core:
<ItemsControl x:Class="Grapes.Common.Controls.TiledGrid.TiledGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Grapes.Common.Controls.TiledGrid"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" x:Name="itemsGrid"
ScrollViewer.CanContentScroll="True" >
<!--ItemTemplate="{Binding ItemTemplate}"-->
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border BorderBrush="Black" BorderThickness="1"
Padding="3" Margin="3" >
<HeaderedContentControl
HeaderTemplate="{Binding HeaderTemplate,ElementName=itemsGrid}" Header="{Binding}"
ContentTemplate="{Binding ItemTemplate,ElementName=itemsGrid}" Content="{Binding}"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch"
>
<HeaderedContentControl.Template>
<ControlTemplate TargetType="HeaderedContentControl">
<DockPanel>
<ContentPresenter DockPanel.Dock="Top" ContentSource="Header" />
<ContentPresenter />
</DockPanel>
</ControlTemplate>
</HeaderedContentControl.Template>
</HeaderedContentControl>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<local:UniformGridPanel Rows="{Binding RowCount,ElementName=itemsGrid}"
Columns="{Binding ColumnCount,ElementName=itemsGrid}"
>
</local:UniformGridPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<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" FlowDirection="RightToLeft" CanContentScroll="True" SnapsToDevicePixels="True"
>
<ItemsPresenter FlowDirection="LeftToRight">
</ItemsPresenter>
</ScrollViewer>
</Border>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
What can I do to stop the ScrollViewer in the ItemsControl.Template from handling the MouseWheel event?
Thanks in Advance!
Mike.

WPF ItemsControl scrollbar

Using ItemsControl to display a collection of items on a Canvas.
Probelm is that I can't see all the items on my screen (need to use Scrollbars), I've checked this post out and tried the same but it doesn't work for me, the Scrollbar is shown but disabled. My XAML:
<Grid>
<DockPanel>
<ScrollViewer>
<ItemsControl ItemsSource={Binding MyCollection}>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
....
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>
</Grid>
ItemsControl by default doesn't have ScrollViewer in it's Template unlike ListBox.
Get rid of the outer scrollViewer and set the Template of ItemsControl to contain ScrollViewer. Also, I don't see any usage of DockPanel when you already wrap ItemsControl inside Grid.
Change layout something like this:
<Grid>
<ItemsControl ItemsSource={Binding MyCollection}>
<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>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
....
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>

Unwanted scroll on click on last item in ItemsControl

Case: ItemsControl with Virtualizing enabled (performance). Contains checkboxes/textboxes/etc. However, clicking on checkbox/textbox on last visible item causes itemscontrol to scroll down instead of selecting the checkbox/textbox.
With virtualizing disabled, everything works fine...
I have tried a lot of things (using ListView, wrapping it in larger panel, etc.). No luck.
ItemsSource is set in code behind to a large dataset of testitems with properties Name and ID.
<Window x:Class="ListViewTestApplication.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="650" Width="525" Background="AliceBlue">
<ItemsControl x:Name="MainListView" VirtualizingStackPanel.IsVirtualizing="True"
ScrollViewer.CanContentScroll="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid DataContext="{Binding}" Width="525">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Height="50" Grid.Row="0" Content="{Binding Path=Name}"/>
<CheckBox Height="50" Content="Checkbox" Grid.Row="1" />
<TextBox Height="50" Grid.Row="2" />
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<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>
</ItemsControl>

Windows Themes ButtonChrome Border

I have created my own button based on icrosoft_Windows_Themes2:ButtonChrome. I want to get rid of the default border and i've tried setting it to null or transparent but still i get a white border.
Here's my markup:
<Microsoft_Windows_Themes2:ButtonChrome x:Name="ibAero" Visibility="Collapsed" SnapsToDevicePixels="true" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}" RoundCorners="True" Background="{TemplateBinding Background}" BorderBrush="Transparent" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderPressed="{TemplateBinding IsPressed}" OverridesDefaultStyle="True">
<Border x:Name="bd" CornerRadius="10" BorderThickness="1" BorderBrush="{Binding ElementName=IB, Path=BorderBrush}">
<StackPanel Orientation="Horizontal" Margin="8,1,5,1">
<TextBlock Text="{Binding ElementName=IB, Path=Text}" Foreground="{Binding ElementName=IB, Path=TextForeground}" Margin="{Binding ElementName=IB, Path=TextMargin}" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</Microsoft_Windows_Themes2:ButtonChrome>
EDIT:
Ok. I've changed the markup like this:
<Border x:Name="ibAero" Visibility="Collapsed" Height="{TemplateBinding Height}" Width="{TemplateBinding Width}" CornerRadius="3" BorderThickness="1" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}">
<StackPanel x:Name="ibAeroPanel" Orientation="Horizontal" Margin="8,1,5,1">
<Image Source="{Binding ElementName=IB, Path=Image}" Width="{Binding ElementName=IB, Path=ImageWidth}" Height="{Binding ElementName=IB, Path=ImageHeight}"/>
<TextBlock Text="{Binding ElementName=IB, Path=Text}" Foreground="{Binding ElementName=IB, Path=TextForeground}" Margin="{Binding ElementName=IB, Path=TextMargin}" VerticalAlignment="Center"/>
</StackPanel>
</Border>
How do i set the default style in my usercontrol?
The answer to this problem is posted by Meleak in this link: How to remove ButtonChrome border (when defining the template of a border)?
The reason you get that white border is because it is added IN CODE in the ButtonChrome control. There is NO WAY to achieve the solution to this with templating. The only way to remove the border is write your own version of the control.
I googled this issue and found numerous answers by people offering template "solutions". None of them will ever possibly work as suggested.
Add Meleak's modified ButtonChrome.cs control to your library of customized WPF controls (ComboBox with disabled F4 key being another in my personal inventory) and you are good to go.
I would recommend not including the Button Chrome in your template. It would require extra work if you want to recreate some of the nice effects it provides on mouseover and pressed, but it will get rid of the border.

Resources