WPF Disable mousewheel on ScrollViewer and let children handle it - wpf

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.

Related

XAML: How to bind TabControl nested element to Attached Property of TabItem

I have been searching for a "pure" XAML solution for this problem but just cannot find it.
My goal would be to only create an Attached Property in code behind but the rest should be XAML only without creating a Custom Control or User Control. But I'm not sure whether this is possible at all and if, how to make the connection between a nested element inside the TabControl template and an Attached Property set in a TabItem
I'd have a boilerplate Attached Property of string with [AttachedPropertyBrowsableForType(typeof(TabItem))] and/or [AttachedPropertyBrowsableForType(typeof(TabControl))] inside my MainWindow class and the following XAML
<Window x:Class="AP_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AP_Test"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="800">
<Window.Resources>
<Style TargetType="{x:Type TabControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid Name="templateRoot" ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
<Grid.ColumnDefinitions>
<ColumnDefinition Name="ColumnDefinition0"/>
<ColumnDefinition Name="ColumnDefinition1" Width="0"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Name="RowDefinition0" Height="Auto"/>
<RowDefinition Name="RowDefinition1" Height="*"/>
</Grid.RowDefinitions>
<TabPanel Name="headerPanel"
Background="Transparent"
Grid.Column="0"
IsItemsHost="true"
Margin="2,2,2,0"
Grid.Row="0"
KeyboardNavigation.TabIndex="1"
Panel.ZIndex="1"/>
<Border Name="contentPanel"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Background="{TemplateBinding Background}"
Grid.Column="0"
KeyboardNavigation.DirectionalNavigation="Contained"
Grid.Row="1"
KeyboardNavigation.TabIndex="2"
KeyboardNavigation.TabNavigation="Local">
<DockPanel Background="White">
<Grid Name="TabControlHeader" DockPanel.Dock="Top" Height="65">
<Label x:Name="SelectedItemTitle" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="24" Content="How to bind to AP ItemTitle?"/>
</Grid>
<Grid Name="Detail" Margin="8,0,8,8">
<Border BorderThickness="3,3,0,0" BorderBrush="DarkGray" CornerRadius="3"/>
<Border BorderThickness="2,2,1,1" BorderBrush="LightGray" CornerRadius="3"/>
<Border BorderThickness="1,1,1,1" BorderBrush="White" CornerRadius="3" Margin="3,3,-1,-1" Padding="5">
<Viewbox>
<ContentPresenter Name="PART_SelectedContentHost"
ContentSource="SelectedContent"
Margin="{TemplateBinding Padding}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Viewbox>
</Border>
</Grid>
</DockPanel>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<TabControl x:Name="TabCtl">
<TabItem Header="Tab1" local:MainWindow.ItemTitle="Tab1 Title" />
<TabItem Header="Tab2" local:MainWindow.ItemTitle="Tab2 Title" />
<TabItem Header="Tab3" local:MainWindow.ItemTitle="Tab3 Title" />
</TabControl>
</Window>
I'd like the respective title entries to be displayed in the TabControl's SelectedItemTitle label.
Any hints appreciated, even a definitive "That's not possible" would be good to know, so I can stop trying 😁
The property (sub-)path for an attached property needs to be enclosed in parentheses:
Content="{Binding Path=SelectedItem.(local:MainWindow.ItemTitle),
RelativeSource={RelativeSource AncestorType=TabControl}}"
See PropertyPath for Objects in Data Binding for details.
An attached property is not even required. You could as well use the TabItem's Tag property like
<TabItem Header="Tab1" Tag="Tab1 Title"/>
with
Content="{Binding Path=SelectedItem.Tag,
RelativeSource={RelativeSource AncestorType=TabControl}}"

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>
[...]

Load large data set with WPF ContextMenu for RichTextBox

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

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>

ComboBox ControlTemplate Drop Down Button

I was wondering if anyone had an example of how to style/template a combobox to only show a button at its default initial state. Kind of like the DropDownButton gallery for the ribbon bar. I would just like the user to be able to click a button and have the combobox items listed. When the selection is made it does not save the selected item in the text field because there is no text field only a button. Thanks :)
Here's some sample code:
Note that the ContentPresenter and PART_EditableTextBox have been commented out deliberately and they can be taken off from the template.
Also, you may want to customize the appearance of togglebutton and the popup.
<Window x:Class="HiddenTextComboBox.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<ControlTemplate x:Key="HiddenTextComboBox" TargetType="{x:Type ComboBox}">
<Grid>
<ToggleButton x:Name="DropDownToggle"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Margin="-1" HorizontalContentAlignment="Right"
IsChecked="{Binding Path=IsDropDownOpen,Mode=TwoWay,
RelativeSource={RelativeSource TemplatedParent}}">
<Path x:Name="BtnArrow" Height="4" Width="8"
Stretch="Uniform" Margin="0,0,4,0" Fill="Black"
Data="F1 M 300,-190L 310,-190L 305,-183L 301,-190 Z " />
</ToggleButton>
<!--<ContentPresenter x:Name="ContentPresenter" Margin="6,2,25,2"
Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}"
ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}">
</ContentPresenter>
<TextBox x:Name="PART_EditableTextBox"
Style="{x:Null}"
Focusable="False"
Background="{TemplateBinding Background}"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Margin="3,3,23,3"
Visibility="Hidden"
IsReadOnly="{TemplateBinding IsReadOnly}"/>-->
<Popup x:Name="PART_Popup"
IsOpen="{TemplateBinding IsDropDownOpen}">
<Border x:Name="PopupBorder"
HorizontalAlignment="Stretch" Height="Auto"
MinWidth="{TemplateBinding ActualWidth}"
MaxHeight="{TemplateBinding MaxDropDownHeight}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="Black" Background="White" CornerRadius="3">
<ScrollViewer x:Name="ScrollViewer" BorderThickness="0" Padding="1">
<ItemsPresenter/>
</ScrollViewer>
</Border>
</Popup>
</Grid>
</ControlTemplate>
</Window.Resources>
<Grid>
<ComboBox Height="23" Width="23" Template="{StaticResource HiddenTextComboBox}">
<ComboBoxItem>First</ComboBoxItem>
<ComboBoxItem>Second</ComboBoxItem>
<ComboBoxItem>Third</ComboBoxItem>
</ComboBox>
</Grid>
</Window>
Code adapted from: Customizing the Appearance of an Existing Control by Creating a ControlTemplate

Resources