In XAML, how can I keep an ellipse being a circle? - wpf

I'm getting XAML-blind I'm afraid. I'm developing a MS Surface application and I have an ellipse inside a ScatterViewItem (a container an end user can resize). I would like to keep the ellipse a circle (width == height) and keep it as big as possible (the lowest value of width/height of the SVI should be taken for both width/height properties of the ellipse).
A XAML only solution (using property triggers or similar) is prefered.
Your help is much appreciated as always.

I stumbled over this question a few minutes ago and found a much better solution than #Paul Betts (I'd comment on his answer if I could, but I can't)
You can simply use <Ellipse Stretch="Uniform" /> to get a circle.
Source: http://forums.silverlight.net/t/160615.aspx

Would a simple Viewbox do the trick? E.g.
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Canvas Width="100" Height="100">
<Ellipse Fill="Red" Width="100" Height="100" />
</Canvas>
</Viewbox>
The Viewbox will scale its contents to fill the area of the Viewbox, and by default does the scaling proportionally. The specified horizontal and vertical alignments keep the Ellipse centered when it cannot be stretched to the full size (because of the proportional scaling).

<Ellipse x:Name="anEllipse" Width={Binding Path=ActualHeight ElementName=anEllipse} />
You could probably get away with not naming this if you did a relative binding as well.

Related

Drawing dynamically positioned overlays on Images in wpf

I have an Image control in my view bound to BitmapSource prop in my View Model. This property is updated with images from a camera in my Model class. To get started with drawing shapes on images (so 1 control ON another),after
reading a similar post, I tried the following with a simple Rectangle
shape with Zindex=2 so it should act as an overlay over the image. But the
below doesn't work & all I see is the image from the camera
<Canvas>
<DockPanel Width="400" Height="250">
<Label DockPanel.Dock="Top" HorizontalAlignment="Center"
Content="IMAGE FROM CAMERA" Width="Auto"/>
<Image x:Name="CamImageDisplay"
DockPanel.Dock="Left"
Source="{Binding CurrentImage, Mode=OneWay}"
Stretch="None" Width="Auto"/>
<Rectangle Width="10" Height="5"
Fill="CadetBlue"
Panel.ZIndex="2" />
</DockPanel>
</Canvas>
I come from an MFC background where drawing shapes on bitmaps was as
easy as calling Draw3dRect(...). Having said that, my goal is to draw
a collection of shapes (just rectangles & circles) that will have
different co ordinates with each new image.
Could some one please
explain in simple terms or point to some reference that will show how
I can achieve this. Yes, there are other similar questions, but they
are really not quite aligned with my objectives. Thank you & please ask for clarifications if I am unclear in how I have asked my question.

How do I properly draw and scale a Canvas as a WPF background to a control?

I have a StackPanel that needs to contain drawn background. Specifically, my StackPanel needs to have the ability to grow and the rectangle must grow with the StackPanel, but must remain pseudo-anchored to each side at a fixed position.
I've attempted to use the Canvas.Left, Canvas.Right, Canvas.Top and Canvas.Bottom attached properties, but so far they've not worked. Furthermore, this does seem to work when drawing within Canvas objects, just not when they are embedded within a VisualBrush set as a background. How can I accomplish drawing this resizable, rectangular background within my StackPanel?
Below is the state of my current code. I've tried various approaches but none seem to work.
My Code:
<StackPanel DockPanel.Dock="Right" Orientation="Vertical" VerticalAlignment="Center">
<StackPanel.Background>
<VisualBrush Stretch="None">
<VisualBrush.Visual>
<Canvas Background="Magenta" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
Rectangle Fill="#FFDDECF7" Canvas.Left="20" Canvas.Top="20" Canvas.Bottom="20" Canvas.Right="0"/>
</Canvas>
</VisualBrush.Visual>
</VisualBrush>
</StackPanel.Background>
...
</StackPanel>
This currently doesn't render anything. I set the canvas background to magenta just so I could see if it were drawing, and I'm not even seeing that. Other attempts have drawn the canvase, however, the blue rectangle is always stretched to fill the window, regardless of attached canvas property settings.
Sample:
The image below is a sample of what I want. Again, I'm using an ugly Magenta color to show the offset of the internal, blue rectangle. As the StackPanel grows or shrinks, the rectangle needs to be affixed to the top, left, right and bottom.
My suggestion is to place the stackpanel inside a grid:
<Grid DockPanel.Dock="Right" VerticalAlignment="Center" Background="Magenta">
<Rectangle Margin="20" Fill="#FFDDECF7"/>
<StackPanel Orientation="Vertical">
no background...
</StackPanel>
</Grid>
Wrap Canvas into a ViewBox, then work on a ViewBox. As far as I know Canvas doesn't support scalling too well.

Magnifing glass in WPF

How can I create a non-circular magnifying glass in WPF? This has to work on controls not just an image. Every example I find online is either circular only or only works on images.
For example I have a slider, and I'd like to turn the thumb into a rectangular magnifying region to show enlarged ticks (as my ticks are displayed in the Slider track itself, not below it). I have created all the styles necessary I am just missing the ability to magnify contents underneath the thumb (as the thumb sits on top of the controls / display)
<Slider Ticks="{Binding MyCollection}" />
Thanks
It's pretty easy to just make your own 'magnifying' control. You could use a VisualBrush with a Visual property taken from the source (that you want to magnify) painted onto a plain Rectangle. See the Using VisualBrush to Show a Magnifying Glass page on the Ian G on Tap website as an example.
Better yet, here is a very simple example of a VisualBrush that is painting a Rectangle in the right column of a Grid, magnifying an Image from the left column of a Grid. You can tweak it to your liking:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Name="Image" Source="Images/BlackLogo.ico" Width="150" Height="150" />
<Rectangle Grid.Column="1">
<Rectangle.Fill>
<VisualBrush Visual="{Binding ., ElementName=Image}"
Viewport="50,100,300,300" ViewportUnits="Absolute" />
</Rectangle.Fill>
</Rectangle>
</Grid>

Image control in WPF Stretches Image When Stretch Set to None

I have an image control inside a grid displaying a 16x16 icon. But for some reason even though I set the properties so it would remain 16x16 it looks stretched.
Code :
<UserControl x:Class="ChatControls.UserListItem"
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"
mc:Ignorable="d" d:DesignHeight="28" d:DesignWidth="132">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" MinWidth="24" MaxWidth="24" />
<ColumnDefinition Width="171*" />
</Grid.ColumnDefinitions>
<Image Name="imgIcon" Source="/ChatControls;component/Images/NormalUser.png" VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="None" />
<Label Content="Muhammad[A]" Grid.Column="1" Name="lblNick" VerticalContentAlignment="Center" Padding="8,5,5,5" />
</Grid>
</UserControl>
Is there any reason for this?
UPDATE 1:
Yes at runtime also :(
Many thanks in advance.
Actually, I've seen that regularly with PNG images. It seems that the default resolution for PNG is 72dpi, while the default screen resolution in WPF is 96dpi. WPF tries to take this into account by rendering png bitmaps scaled to 133% of their pixel size, which is technically correct but normally not what the user wants. You can either use a gif or jpg instead, or you can combine the image with a LayoutTransform scaling it to 0.75 of its size, or just stick with setting the size of the image control explicitly.
I find I often have to explicitly specify the Width and Height of Image controls to get them to appear correctly:
<Image
Name="imgIcon"
Source="/ChatControls;component/Images/NormalUser.png"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Width="16"
Height="16"
/>
First of all, your XAML definition of your 171* is a bit odd. Your best approach is to do this:
<Grid.ColumnDefinitions>
<ColumnDefinition Width="24" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
You need to look into XAML layout passes in order to understand what this is doing.
Secondly, because you're using a dynamic image source (loaded as a URI), it will be streamed so the width during the first layout pass will be 24, but after the image has been streamed, the control will resize dynamically. If you want to enforce sizing, your best bet is to use a border around the image as a 0 width container. Like this
<Border Grid.Column="0" Grid.Row="0" BorderThickness="0" BorderBrush="Black">
<!-- UniformToFill: Scale to completely fill output area.
Aspect ratio is preserved. Cropping may occur.-->
<Image
Source="sampleImages/gecko.jpg"
Stretch="UniformToFill" />
</Border>
Enforcing a width and a height around an image is a shorthanded way of doing this. The other thing you may want to do is to explicitly define the way the source image is loaded like this:
<Image Width="200">
<Image.Source>
<BitmapImage DecodePixelWidth="200"
UriSource="C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures\Water Lilies.jpg" />
</Image.Source>
</Image>
Which will not load the full image but will resize before load as opposed to dynamically. For further reference review http://msdn.microsoft.com/en-us/library/ms748873.aspx
I agree with the accepted answer, but I don't think it explains why, it just explains that it works.
It happens because of the image pixels that is dependent on the screen resolution, it should be device independent so that to remains same on any screen resolution
So use this to do so.
<Image Width = "24" Height = "24" RenderOptions.BitmapScalingMode="NearestNeighbor" RenderOptions.EdgeMode="Aliased" Stretch = "None"/>
replace Width and Height with the original size of the image
This'll help you

Perfect Center on WPF Canvas

Since the canvas requires a Top/Left for placement, if you want to center something, is adding a grid at the proper Canvas.Top with HorizontalAlignment="Center" the best way to do it, or is there a better way?
This snip is a 150X300 canvas, with some content centered in a grid ....
<Canvas Width="150" Height="300">
<Grid Canvas.Top="75" Width="106" HorizontalAlignment="Center">
{whatever you want centered}
</Grid>
</Canvas>
Guy's solution works, but you may have to tweak z-order and visibility if you're juggling hit testing.
Another alternative is having the Grid inside the Canvas (as you've specified in your XAML) with the Height/Width set to (or bound to) the Height/Width of the Canvas. Then setting HorizontalAlignment/VerticalAlignment to Center for the contents of your Grid.
I'm not sure if this will meet your exact requirement, but if you put both the canvas and the content inside a grid as peers, it will get you a centered result:
<Grid>
<Canvas Width="150" Height="300"/>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Width="106" Content="Click"/>
</Grid>

Resources