Binding Size of Canvas Background - wpf

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.

Related

Control size of Canvas in ScrollViewer

I am writing a custom control for image display and interaction. Some of the features it needs is zooming and panning as well as drawing a custom region of interest, i.e. drawing a rectangle on top of the displayed frame with arbitrary position and size. Zooming and panning features are done and work nicely, I'm using a ScrollViewer, a scale transform and some event handlers for mouse clicking and moving in the C# code.
For the custom selection feature I want to add a canvas on top of the frame since that's the only way I know of that allows arbitrary positioning of a rectangle. In order for any shapes on the canvas to be mappable to image coordinates I need of course the canvas to exactly line up with the image so size and position must be the same. I also would like the image to keep adjusting to window resizes as it does without any canvas. Since Canvas doesn't automatically resize itself to anything I want to bind its dimensions to the size of the image like so (this is from the control template for the custom control):
<ScrollViewer x:Name="scrollViewer" Grid.Column="0" Grid.Row="1" CanContentScroll="True" PanningMode="Both" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible">
<Grid>
<Image x:Name="screen" Panel.ZIndex="0" Cursor="Cross" Source="{TemplateBinding ColoredFrame}"/
<Canvas x:Name="testCanvas" Panel.ZIndex="1" Background="Transparent" Width="{Binding ActualWidth, ElementName=screen}" Height="{Binding ActualHeight, ElementName=screen}"/>
<Grid.LayoutTransform>
<TransformGroup>
<RotateTransform Angle="{Binding RotationAngle, RelativeSource={RelativeSource TemplatedParent}}"/>
<ScaleTransform x:Name="scaleTransform" ScaleX="{Binding ZoomFactor, RelativeSource {RelativeSource TemplatedParent}}" ScaleY="{Binding ZoomFactor, RelativeSource={RelativeSource TemplatedParent}}"/>
</TransformGroup>
</Grid.LayoutTransform>
</Grid>
</ScrollViewer>
However, I am getting weird behaviour with this - when I use bindings for both Width and Height of the canvas to ActualWidth and ActualHeight of the image, like in the above code, it will automatically resize itself only when the size increases (when the user increases the size of the window) but not when it decreases. Any size increase is permanent and when decreasing the window again, one would have to scroll as the size of the image and canvas never decrease. This does not happen when I bind only one of the dimensions (width or height) and set the other one to a constant value. Binding modes (one way / two way) have no effect either.
I'm probably missing something really obvious but I've spent hours trying to figure this out and I am at a loss. Any help would be appreciated.
as far as I know Canvas does not have good sizing options. I think an Adorner will do what you try to achieve. For an example and additional information please have a look here: https://learn.microsoft.com/de-de/dotnet/framework/wpf/controls/adorners-overview
Happy coding
Tim

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.

Change the MahApps Metro Split ButtoniIcon size

I'm trying to use the split button control described here:
http://mahapps.com/controls/split_dropdownbutton.html
I'm also using the MahApps resource pack with the icons collection. I want to re-size the control to a height of 40px, but the icon stays to its native height of 76px, resulting in it getting cropped, as shown below.
Any ideas how to get around this?
The SplitButton from MahApps.Metro has a property called IconTemplate. To this property you can assign a DataTemplate and there you can add almost arbitrary content, which will be put in place of the icon itself.
For example you could put a Rectangle control with fixed Height and/or Width. And setting its OpacityMask to your desired icon, will show the icon in smaller size.
In XAML it looks like this:
<controls:SplitButton Orientation="Horizontal">
<controls:SplitButton.IconTemplate>
<DataTemplate>
<Rectangle VerticalAlignment="Center" Height="35" Width="35" Fill="{DynamicResource BlackColorBrush}">
<Rectangle.OpacityMask>
<VisualBrush Visual="{StaticResource appbar_globe}" />
</Rectangle.OpacityMask>
</Rectangle>
</DataTemplate>
</controls:SplitButton.IconTemplate></controls:SplitButton>
controls is the alias for the MahApps.Metro-namespace and may differ in your project.

Text disappear while FlowDirection set to RightToLeft

Please check the code below. I am working with Silverlight.
<Canvas x:Name="LayoutRoot" Background="blue" Width="100" FlowDirection="RightToLeft">
<TextBlock x:Name="tb2" Text="abcd" Canvas.Top="100" Canvas.Left="20" Foreground="White"/>
</Canvas>
FlowDirection set to RightToLeft in canvas or TextBlock makes the text to disappear..Any idea what is causing this problem. and how to make it work?
From my short tests it seems FlowDirection is available on Canvas only because it's part of UIElement. But using it on a Canvas doesn't really make much sense. A canvas is just that - a canvas on which you can place objects in exact places.
FlowDirection works quite well when using inside a Grid. I don't know what you're trying to achieve, but I'd start with rewriting your control to use Grid rather than Canvas.

Unintended opacity mask change by child control

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?

Resources