Unintended opacity mask change by child control - wpf

I want to make a canvas which has rounded border. I think I can implement it by OpacityMask. but it's a hard to me.
<Canvas Background="Red" ClipToBounds="True" x:Name="can">
<Canvas.OpacityMask>
<!--czc.png is opacity mask source which represents a rounded rectangle.-->
<ImageBrush ImageSource="/WpfApplication3;component/Images/czc.png"/>
</Canvas.OpacityMask>
<Image Source="/WpfApplication3;component/Images/1lvhuman.jpg" Margin="-129,56,192,46" Canvas.Left="193" Canvas.Top="25" Height="186" Width="153" />
</Canvas>
figure 1. is the Image in canvas that don't hanged in the Canvas's border. In the contrary, the Image of figure 2 hanged in left border of the Canvas. when hanged in there, OpacityMask was changed.

Why are you using Canvas? Can you just use a Border with a BorderRadius instead?

Related

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.

WPF Hyperlinked Image with rounded corners

Question: How to create hyperlinked Image with rounded corners in WPF/XAML?
So far, existing code for hyperlinked image (no rounded corners) is working (see below):
Hyperlinked Image (WPF XAML)
<TextBlock Name="txtbFooterRight" >
<Hyperlink Name="lnkImg" TextDecorations="None"
NavigateUri="http://webinfocentral.com"
ToolTip="Navigate to web page">
<Image Name="someName" Source="some url" />
</Hyperlink>
</TextBlock>
Hyperlinked image code behind (C#):
lnkImg.RequestNavigate += (s, e) => {Process.Start(e.Uri.ToString()); };
Image control with rounded corners (no hyperlinks) is implemented as:
Image with rounded corners (WPF/XAML):
<Border Name="brdRounded" BorderThickness="0" CornerRadius="10">
<Border.Background >
<ImageBrush>
<ImageBrush.ImageSource>
<BitmapImage UriSource="some Uri to .jpg" />
</ImageBrush.ImageSource>
</ImageBrush>
</Border.Background>
</Border>
I need to "round the corners" of the hyperlinked image (WPF/XAML), probably combining aforementioned techniques. Thanks and regards,
Note: I've accepted the answer posted by user #lisp with just minor fix: Border background color should match the surrounding color in order to avoid slight "color leakage". Kudos to the author!
On a separate note: it was an eye-opening experience on how relatively difficult it is to achieve such simple effect while using WPF/XAML comparing to HTML5/CSS3 (see for, example, essentially the same effect on rounded corner image at: http://infosoft.biz/SlideShowCSS.aspx). It seems like WPF folks at Microsoft should take a note...
Border is used for rounded corners. But in your case if you simply put TextBlock inside of Border, you wouldn't get the desired effect.
Here Corners are made transparent using a border. Grid is used so that Border stretches exactly to the size of TextBlock.
<Grid>
<Border Name="CornersMask" Background="White" CornerRadius="20"/>
<TextBlock>
<TextBlock.OpacityMask>
<VisualBrush Visual="{Binding ElementName=CornersMask}"/>
</TextBlock.OpacityMask>
<Hyperlink ...>
<Image Name="someName" Source="some url" />
</Hyperlink>
</TextBlock>
</Grid>
TextBlock is displayed on top of Border, and because of that and antialiasing you may experience slight whiteness on the rounded edges. Either change the Border background to the surrounding background color, or enclose Border in another container that will autostretch it e.g. Border of Grid, and set it's Visibility to Hidden.
<Border Visibility="Hidden">
<Border Name="CornersMask" Background="White" CornerRadius="20"/>
</Border>
This also solves the problem when the surrounding background is not a SolidColorBrush

Binding Size of Canvas Background

I have a canvas that needs a graphical background using custom images of various sizes, but I want to bind the height and width of the background image to some properties somewhere. right now I have an image displaying as background but its size is fixed. It turns out that the width and height property of the image and of the imagebrush is readonly. Is there anyway to bind the width and height?
p.s I have tried viewport, but it uses a rect object and its width and height are not dependency properties. Then I tried to use one tile of the viewport and put it in a rectangle then I can resize the rectangle to achieve what I want but I cannot figure out how to put a rectangle as the canvas's background. Any Ideas? Thanks in advance.
An easy way is to use a VisualBrush as the Background for the Canvas. Set Stretch to None and then bind the Width and Height of the Image in the Visual
<Canvas ...>
<Canvas.Background>
<VisualBrush Stretch="None">
<VisualBrush.Visual>
<Image Source="SomeSource"
Stretch="Fill"
Width="{Binding ...}"
Height="{Binding ...}"/>
</VisualBrush.Visual>
</VisualBrush>
</Canvas.Background>
<!--...-->
</Canvas>
Can't say that i managed to follow what you're trying to do exactly, but you can use VisualBrush to put the Rectangle as the background of the canvas.
I'm somewhat sure that what you're doing can be solved easily - but I couldn't really understand what it is you're trying to do.

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>

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

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.

Resources