I am not a WPF expert so please excuse my inappropriate use of terms. I have a ScrollViewer where I am displaying a captured image. And I have a slider with which I am zooming the image in and out. Zooming works fine, but the scrollbars are not changing their size. Hence when the image goes beyond the boundaries, I cannot scroll and view it. As if the scrollbars become useless because they haven't changed their size. Here is my XAML:
The Slider:
<Slider DockPanel.Dock="Right" Width="100" VerticalAlignment="Center" Minimum="0.2" Maximum="5"
Interval="1" Value="{Binding ScaleFactor}"/>
The rest of XAML:
<Border BorderThickness="1" BorderBrush="Black" Grid.Row="1">
<Grid>
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
CanContentScroll="True">
<ItemsControl ItemsSource="{Binding ItemCollection}" Margin="0"
Width="{Binding Root.Boundary.Width}" Height="{Binding Root.Boundary.Height}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas>
<Canvas.LayoutTransform>
<ScaleTransform ScaleX="{Binding ScaleFactor}"
ScaleY="{Binding ScaleFactor}"CenterX="0" CenterY="0"/>
</Canvas.LayoutTransform>
</Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Image x:Name="capturedImage"
Source="{Binding Image}"
Width="{Binding Boundary.Width}"
Height="{Binding Boundary.Height}"/>
<Path x:Name="captureContour"
Data="{Binding Outline}"
Stroke="Black" StrokeThickness="4" Opacity="0.5"
StrokeLineJoin="Round">
<Path.LayoutTransform>
<ScaleTransform ScaleX="{Binding OutlineScale.X}"
ScaleY="{Binding OutlineScale.Y}" CenterX="0"CenterY="0"/>
</Path.LayoutTransform>
</Path>
</Grid>
<DataTemplate.Triggers>
<Trigger SourceName="capturedImage" Property="IsMouseOver"
Value="True">
<Setter TargetName="captureContour" Property="Stroke"
Value="Blue"/>
<Setter TargetName="captureContour" Property="BitmapEffect">
<Setter.Value>
<DropShadowBitmapEffect/>
</Setter.Value>
</Setter>
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
</Border>
The issue is due to the Canvas used as ItemsPanel. as Canvas does not expand or collapse with the size of it's children so ScrollViewer does not detect the change.
As a quick solution change the ItemsPanel to Grid. Since your example does not seems to be using Canvas properties i.e. Canvas.Left or Canvas.Top, this change may not make any difference in the appearance.
example
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid.LayoutTransform>
<ScaleTransform ScaleX="{Binding ScaleFactor}"
ScaleY="{Binding ScaleFactor}"
CenterX="0"
CenterY="0" />
</Grid.LayoutTransform>
</Grid>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
make sure to have HorizontalAlignment="Left" VerticalAlignment="Top" in grid otherwise it may appear weird when you zoom.
give it a try and see if this is what you are looking for.
OK guys, here is what needs to be done in order to make it work:
<ItemsControl ItemsSource="{Binding ItemCollection}" Margin="0" Width="{Binding CanvasWidth}"
Height="{Binding CanvasHeight}"/>
Related
I am doing a custom WPF UserControl and i need to draw a variable size text that is rotated 45 degrees and spaced evenly horizontally, like the next image (being the red bars the text):
With the following code:
<UserControl.Resources>
<ResourceDictionary>
<DataTemplate x:Key="CheckTemplate">
<!-- description -->
<TextBlock
VerticalAlignment="Bottom" Margin="-10,0,0,0" Text="{Binding Check.Name}" Background="Transparent" x:Name="AAA">
<TextBlock.LayoutTransform>
<RotateTransform Angle="-45" />
</TextBlock.LayoutTransform>
</TextBlock>
<DataTemplate.Triggers>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter Property="Margin" Value="0" TargetName="AAA" />
</Trigger>
</DataTemplate.Triggers>
</DataTemplate>
<ItemsPanelTemplate x:Key="ChecksItemsPanel">
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
/>
</ItemsPanelTemplate>
</ResourceDictionary>
</UserControl.Resources>
<StackPanel x:Name="RootPanel" Margin="5">
<ItemsControl
x:Name="WorkflowChecksItemsControl"
ItemTemplate="{DynamicResource CheckTemplate}"
ItemsPanel="{DynamicResource ChecksItemsPanel}"
ItemsSource="{Binding WorkflowChecks}" />
</StackPanel>
i only managed to do something like this:
How can i do this using XAML?
In this project i am also using Telerik UI for WPF, and i can use theirs framework if it is simpler.
You may combine a -90° LayoutTransform of the ItemsPanel with a 45° RenderTransform of each TextBlock. For the horizontal distance, simply set the TextBlocks' Height.
<ItemsControl ItemsSource="{Binding WorkflowChecks}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel>
<StackPanel.LayoutTransform>
<RotateTransform Angle="-90"/>
</StackPanel.LayoutTransform>
</StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Check.Name}" RenderTransformOrigin="0,1">
<TextBlock.RenderTransform>
<RotateTransform Angle="45"/>
</TextBlock.RenderTransform>
</TextBlock>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
Result:
Either it is super simple and I just didn't find the solution yet or I'll start to go insane soon.
I just want to draw a Line in an ItemsControl on a Canvas and that Line should have an Ellipse on both edges. Like this:
My ItemsControl looks like this:
<ItemsControl ItemsSource="{Binding Connections}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type systemEnvironmentViewModels:SystemEnvironmentConnectionViewModel}">
<systemEnvironment:ConnectionView/>
</DataTemplate>
<Style TargetType="ContentPresenter"> <!-- this does only make it worse -->
<Setter Property="Canvas.Left" Value="{Binding Connection.FirstElementCoordinate.X}"/>
<Setter Property="Canvas.Top" Value="{Binding Connection.FirstElementCoordinate.Y}"/>
</Style>
</ItemsControl.Resources>
</ItemsControl>
And the View that is used as DataTemplate:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Ellipse x:Name="DependencyEllipse" Width="10" Height="10" Fill="Black" Grid.Column="0"/>
<Line X1="{Binding Connection.FirstElementCoordinate.X}" X2="{Binding Connection.SecondElementCoordinate.X}"
Y1="{Binding Connection.FirstElementCoordinate.Y}" Y2="{Binding Connection.SecondElementCoordinate.Y}"
Stroke="Black" StrokeThickness="5" x:Name="ConnectionLine" Grid.Column="1"/>
<Ellipse x:Name="SecondDependencyEllipse" Width="10" Height="10" Fill="Black" Grid.Column="2"/>
</Grid>
The Result does look nothing like I want and I know that using a Grid with columns probably doesn't work but it's the closest I can think of that allows to split the elements like I want.
Also the Style for the ContentPresenter seems to be wrong, because without it my Line gets drawn like I want but the Ellipses are wrong
Should I go for another ItemsControl just for the Ellipse?
Help is much appreciated.
Do not use an Ellipse and don't put elements in Grid columns.
Instead, use Path elements with EllipseGeometries. The following example assumes that the FirstElementCoordinate and SecondElementCoordinate properties are of type System.Windows.Point. If that is not the case, use an appropriate Binding Converter.
<Canvas>
<Line X1="{Binding Connection.FirstElementCoordinate.X}"
Y1="{Binding Connection.FirstElementCoordinate.Y}"
X2="{Binding Connection.SecondElementCoordinate.X}"
Y2="{Binding Connection.SecondElementCoordinate.Y}"
Stroke="Black" StrokeThickness="5"/>
<Path Fill="Black">
<Path.Data>
<EllipseGeometry Center="{Binding Connection.FirstElementCoordinate}"
RadiusX="5" RadiusY="5"/>
</Path.Data>
</Path>
<Path Fill="Black">
<Path.Data>
<EllipseGeometry Center="{Binding Connection.SecondElementCoordinate}"
RadiusX="5" RadiusY="5"/>
</Path.Data>
</Path>
</Canvas>
Hi all I've looked through several of these forum posts with different solutions but can't seem to get it. My style
<Style x:Key="ScaleStyle" TargetType="Image">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Grid.ZIndex" Value="1"/>
<Setter Property="RenderTransform">
<Setter.Value>
<ScaleTransform ScaleX="2.5" ScaleY="2.5"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
My UniformGrid with images:
<ListView Grid.ColumnSpan="5" Grid.Row="11" Name="Thumbnails">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="5"/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate>
<Image Style="{StaticResource ScaleStyle}" RenderTransformOrigin="0.5,0.5" Source="{Binding}" Height="100" Width="100" Margin="3">
</Image>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
What happens with this is that the image gets bigger but inside the uniform grid which makes it overlap with other images and is just not nice looking.
On the other hand I tried using a tooltip popup and it would open a new popup but the image inside would be a giant zoom of the corner of the image.
<Image Name="Image" Source="/WpfApplication1;component/Images/Tulips.jpg" Height="100"
Stretch="Uniform">
<Image.ToolTip>
<ToolTip DataContext="{Binding PlacementTarget,
RelativeSource={RelativeSource Self}}">
<Border BorderBrush="Black" BorderThickness="1" Margin="5,7,5,5">
<Image Source="{Binding Source}" Stretch="None" />
</Border>
</ToolTip>
</Image.ToolTip>
The problem might be that the original images are very large and in the Uniform grid i set the width and height to a 100 which makes them look like thumbnails but the tooltip seems to reference the original width and height and starts from a corner until it fits the width and height of the tooltip popup which ends up just showing a small part of the original very large picture.
Any help would be greatly appreciated.
Setting the Stretch property of the image to fill will make your image resize to the size of your container.
Currently, I have three different types of objects that I draw to the screen (I'm using a ZoomableCanvas, if that makes a difference): beacons (concentric blue circles), tables (black rectangles), and debugRectangles (gold rectangles. The objects are displayed/layered on the Z-axis according to the order in which they're added to the ItemSource, but it's not always possible for me to add shapes in Z-ordering.
This image shows how it looks, depending on the order of objects being added. I'd like for the shapes to respect the Panel.ZIndexes I've set, and in doing so, look like the top image (except with the gold rectangle in the back).
<Style.Triggers>
<!-- Gold rectangles drawn here (color set in code) -->
<DataTrigger Binding="{Binding type}" Value="rectangle">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Rectangle Fill="{Binding fill}" Stroke="{Binding border}" StrokeThickness="5"
Width="{Binding width}" Height="{Binding height}" Panel.ZIndex="-1"/>
<TextBlock Text="{Binding i}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<!-- Black rectangles drawn here -->
<DataTrigger Binding="{Binding type}" Value="tableBlock">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Rectangle Fill="{Binding fill}" Stroke="Black" StrokeThickness="5"
Width="{Binding width}" Height="{Binding height}" Panel.ZIndex="50"/>
<TextBlock Text="{Binding i}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<!-- Blue circles drawn here -->
<DataTrigger Binding="{Binding type}" Value="beacon">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<Ellipse Fill="DodgerBlue" Width="{Binding outerRadius}" Height="{Binding outerRadius}" Panel.ZIndex="97"/>
<Ellipse Fill="SkyBlue" Width="{Binding innerRadius}" Height="{Binding innerRadius}" Panel.ZIndex="98"/>
<TextBlock Text="{Binding id}" HorizontalAlignment="Center" VerticalAlignment="Center" Panel.ZIndex="99"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
Within a template, they follow the order (I can rearrange the components of a beacon), but relative to each other, no dice. Can anyone identify the issue?
ZoomableCanvas relies upon Panel to render, which means it uses the standard ordering for ZIndex.
<Window x:Class="ZoomableApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<ZoomableCanvas>
<Rectangle Fill="Green" Height="250" Width="250" />
<Rectangle Fill="Red" Height="200" Width="400" Panel.ZIndex="2" />
<Rectangle Fill="Blue" Height="400" Width="200" />
</ZoomableCanvas>
</DockPanel>
</Window>
The problem you are having is that your visual tree looks like this:
ZoomableCanvas
Grid
Ellipse with Panel.ZIndex="98"
Since Ellipse is a child of Grid, the ZOrder doesn't affect the ZoomableCanvas, but instead sets the ZIndex of the Ellipse relative to the other children of the grid. In order to change the layering of the ZoomableCanvas, you need to set the ZOrder property on the child of the ZoomableCanvas – the Grid:
ZoomableCanvas
Grid with Panel.ZIndex="98"
Ellipse
Example:
<DataTemplate>
<Grid Panel.ZIndex="100">
<Rectangle Fill="{Binding fill}" Stroke="Black" StrokeThickness="5"
Width="{Binding width}" Height="{Binding height}" Panel.ZIndex="50"/>
<TextBlock Text="{Binding i}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
If you are using a ListBox, you end up with additional levels in your tree:
ZoomableCanvas
ListBoxItem with ItemContainerStyle setting Panel.ZIndex="98"
Grid
Ellipse
Example of use:
<ListBox>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Panel.ZIndex" Value="98" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
If you have multiple varying ZIndexes, you could expose a property on the data item and bind to that, or use a ItemContainerStyleSelector to do the logic in code-behind.
You can also use Snoop to look at the created tree to identify these sorts of issues.
Have you tried setting the Panel.ZIndex on the Grids?
I have CanContentScroll property set to True in the parent Scrollviewer. This ScrollViewer is applicable to the entire Window. Now, this ScrollViewer has ItemsControl as its child. Each item in the ItemsControl is templated as an Expander and the content of this Expander contains another ItemsControl embedded in the child ScrollViewer. If I remove the child ScrollViewer, the Window content is scrollable, however, if I put it back in, I'm unable to Scroll.
I need the child ScrollViewer because I am limiting the height of the Expander content. When I scroll, the event is not being fired to the parent ScrollViewer in the Visual Tree. How and by using which event I can bubble it to the parent ScrollViewer in the Visual Tree?
This is my code:
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:behaviors="clr-namespace:AttributeSelector" xmlns:sys="clr-namespace:System;assembly=mscorlib"
MinHeight="350" MinWidth="525" MaxWidth="1200" MaxHeight="900" WindowStartupLocation="CenterScreen" SizeToContent="WidthAndHeight">
<sys:Boolean x:Key="BooleanTrue">True</sys:Boolean>
<sys:Boolean x:Key="BooleanFalse">False</sys:Boolean>
<behaviors:TextToHighlightedTextBlockConverter x:Key="TextToHighlightedTextBlockConverter" />
<behaviors:GroupNameToICollectionViewConverter x:Key="GroupNameToICollectionViewConverter" />
<LinearGradientBrush x:Key="LinearGradientBrush" StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="#E3E3E3" Offset="1"/>
<!--<GradientStop Color="#C0C0C0" Offset="1"/>-->
</LinearGradientBrush>
<Style x:Key="MainBorderStyle" TargetType="{x:Type Border}">
<Setter Property="Background" Value="{StaticResource ResourceKey=LinearGradientBrush}" />
<Setter Property="BorderBrush" Value="LightGray" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="5" />
<Setter Property="SnapsToDevicePixels" Value="True" />
</Style>
</Window.Resources>
<DockPanel LastChildFill="True" Margin="10">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="10">
<!-- 3-4 TextBlocks/TextBoxes defined here -->
</StackPanel>
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled" CanContentScroll="True">
<ItemsControl ItemsSource="{Binding UniqueGroups}" ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Margin="5" Style="{StaticResource ResourceKey=MainBorderStyle}">
<Expander x:Name="GroupExpander" Header="{Binding}" IsExpanded="True" Margin="5">
<Expander.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Background="Transparent" Margin="10,0,0,0"
FontWeight="DemiBold" FontSize="16" FontStretch="Expanded"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Expander}}, Path=ActualWidth}"/>
</DataTemplate>
</Expander.HeaderTemplate>
<Expander.Content>
<ScrollViewer Margin="20,5,10,5" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" CanContentScroll="True">
<ItemsControl ItemsSource={Binding SubItems} ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel MaxHeight="300" Orientation="Vertical" UseLayoutRounding="True" IsItemsHost="True" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.GroupStyle>
<GroupStyle>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Horizontal" IsItemsHost="True" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</ItemsControl.GroupStyle>
</ItemsControl>
</ScrollViewer>
</Expander.Content>
</Expander>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</DockPanel>