Enlarge an image on mouseover in Popup in WPF - c#

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.

Related

How to resize width of an image in a listview in WPF?

I have a ListView that contains Image as the Items. I want the width of each image to follow the width of the ListView whenever I resize the Grid that contains it.
<!--Playlists-->
<Grid Column="0">
<ListView Grid.Row="1" Grid.Column="1"
HorizontalAlignment="Stretch"
... >
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<!--Images-->
<ListView.ItemTemplate>
<DataTemplate DataType="{x:Type models:PlaylistModel}">
<Grid HorizontalAlignment="Stretch">
<Image Source="{Binding ImagePath}"
Stretch="Uniform">
</Image>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
<GridSplitter Grid.Column="0" />
Source: http://www.teixeira-soft.com/bluescreen/2016/03/21/c-how-to-make-a-panel-within-a-datatemplate-fill-the-entire-width-of-a-listview-or-itenscontrol-derivative/
This is what happens
As seen here, the width of the image doesn't resize at all. The image size just stays the same even when the size of the ListView changes. However, if I set the width of the Grid inside of DataTemplate then the Image would actually follow that width.
Looks like it was a mistake to use ListView. Changing everything to a ListBox fixed it for me.
Leaving this here if someone encounters the same problem.
<ListBox HorizontalAlignment="Stretch">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate DataType="{x:Type models:PlaylistModel}">
<Image Source="{Binding ImagePath}"
Stretch="Uniform" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

distance between items in listview datatemplate wpf

hi i created a datatemplate for listview now i have 2 problem first is when mouse focus on button my image hide you can see it on below image.
problem 1 and 2
two is The distance between the items is tall and I want their distance being just one line (see below image)
see this image
and this is my datatemplate:
<DataTemplate>
<Border Background="#f0f4f7">
<StackPanel Background="#f5f6fa" Margin="1,1,1,1" VerticalAlignment="Top">
<Border Background="#edf0f5" BorderThickness="5">
<Grid Background="#ffffff" Height="30">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<StackPanel Background="#ffffff" Margin="5" Orientation="Horizontal">
<Button Height="20" Width="20" BorderBrush="Transparent" BorderThickness="0" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.DeleteCommand}">
<Button.Background>
<ImageBrush ImageSource="..\Resources\Delete.png"/>
</Button.Background>
</Button>
<Button Height="20" Width="20" BorderBrush="Transparent" BorderThickness="0" Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.EditCommand}">
<Button.Background>
<ImageBrush ImageSource="..\Resources\Edit.png"/>
</Button.Background>
</Button>
</StackPanel>
<TextBlock Name="txtPhon" Foreground="#7c7f84" HorizontalAlignment="Right" Grid.Column="1" Text="{Binding Path=HomePhoneNumber}"
Margin="0,5,5,5"/>
</Grid>
</Border>
</StackPanel>
</Border>
</DataTemplate>
The problem with mouse making the picture disappear is because of the default template to a button. When you mouseover it gives that blue effect. I think it's in a border which is inside the template so it's above the background.
You can re-template the button to avoid that if you just want your image inside it.
Depending on your exact requirements then you might want slightly different but roughly:
<Button.Template>
<ControlTemplate>
<Border>
<ContentPresenter />
</Border>
</ControlTemplate>
</Button.Template>
You could make the whole template just an image.
Particularly if your icons are one colour, I would recommend using a path and define your icons as geometries in a resource dictionary.
Like the letter in this:
https://social.technet.microsoft.com/wiki/contents/articles/32610.wpf-layout-lab.aspx
The gap between your items.
There's padding in the default itemcontainer styling.
You can avoid that by, again, changing the template something like:
<ListView.ItemContainerStyle>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
I notice you also have a margin set on your TextBlock, I would temporarily change that and see if that's also part of the problem.
<TextBlock Name="txtPhon" Foreground="#7c7f84" HorizontalAlignment="Right" Grid.Column="1" Text="{Binding Path=HomePhoneNumber}"
**Margin="0,0,5,0"/>**
In order to explore this sort of issue I find Snoop is invaluable. It's free.
Once installed run it after your app.
Drag one of the sight + things over your running window.
Mouse over a suspect piece of UI.
Press Ctrl+Shift and it'll show you all the controls in there and their properties. You can change values in the window and explore what effect the change would have immediately.

DataTemplate ListBoxItem for MouseOver

I am trying to get a better understanding of the Templating system with WPF. My design goal here is that I am trying to re-design a component of a software package I work on to use WPF instead of 2D Graphics Librarys. The problem right now is that with 2000 entitys on the screen, pan and zoom is very laggy on a beefy i7 workstation. I wish to redevelop it in WPF to improve performance.
Just as a test, I have created a new project and created a basic XAML/WPF View with a Canvas. This canvas displays ellipses (essentially I am building a 2D Map for planning purposes which has circles of different colors to show different things).
Now, I have my circles showing up fine using a DataTemplate depending on what sort of model the circle is (Circle A or Circle B). When I mouse over the circle, I have the windows default 'blue box' area behind it, which I wish to remove. So far I have managed to use a trigger to change the circle color on mouse over, but I still have the hover area.
<DataTemplate x:Key="HoleBTemplate">
<Grid Width="40" Height="40">
<Ellipse>
<Ellipse.Style>
<Style TargetType="Ellipse">
<Setter Property="Fill" Value="DeepSkyBlue"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Fill" Value="Yellow" />
</Trigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<Ellipse Fill="White" Margin="1" IsHitTestVisible="False" />
<TextBlock
VerticalAlignment="Center"
TextAlignment="Center"
HorizontalAlignment="Center"
Text="{Binding Name}"
IsHitTestVisible="False">
</TextBlock>
<Grid.RenderTransform>
<TranslateTransform X="-20" Y="-20" />
</Grid.RenderTransform>
</Grid>
</DataTemplate>
I created my own ListBox Control which positions the ListBoxItems at an X,Y location inside a canvas.
<controls:ListBoxMap ItemsSource="{Binding Holes}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas></Canvas>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplateSelector>
<controls:PlanTemplateSelector
HoleATemplate="{StaticResource HoleATemplate}"
HoleBTemplate="{StaticResource HoleBTemplate}"/>
</ItemsControl.ItemTemplateSelector>
</controls:ListBoxMap>
TLDR: How do I get rid of the blue highlight area behind the circles on mouse over?
Answer from linked thread above, by Wayne Lo.
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding Content.IsSelected, Mode=TwoWay, RelativeSource={RelativeSource Self}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<ContentPresenter/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

WPF ScrollViewer scroll-bars not changing size

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}"/>

Shapes don't appear to be reacting to setting ZIndex?

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?

Categories