Image Border control wrap question - c#

in the following example, my border wraps around the image. The border does not wrap tightly around the image because I use DecodePixelWidth to keep the aspect ratio. Two sides end up with the border right up against the image, and the other two have gaps from the control. Is there a clean way to have the border wrap the image while keeping the aspect ratio instead of setting the Image stretch to fill.
BitmapImage bitmapIkon = new BitmapImage();
bitmapIkon.BeginInit();
bitmapIkon.CacheOption = BitmapCacheOption.OnLoad;
bitmapIkon.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bitmapIkon.UriSource = new Uri(imagePath);
bitmapIkon.DecodePixelWidth = decodePixelWidth;
bitmapIkon.EndInit();
iImage.MinWidth=width;
iImage.MinHeight=height;
iImage.Source = bitmapIkon;
<Border Width="Auto" Height="Auto" Name="borderImageData" HorizontalAlignment="Center" VerticalAlignment="Center" BorderBrush="Black" BorderThickness="1" CornerRadius="0">
<Image Name="iImage" Stretch="Uniform" />
</Border>

Something like this should work:
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBox Name="iImage" Text="Uniform" Margin="1" />
<Border Name="borderImageData" BorderBrush="Black" BorderThickness="1" CornerRadius="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
</Grid>
So effectively, the Grid sizes to fit the Image plus a margin of 1. The Border then stretches to fill the Grid, and draws it's border on top of the image.
If you are going to be using this a lot, then you may want to wrap it in a custom control.

Related

Set padding of a Canvas in WPF

I have a Canvas with a Rectangle and a Circle inside it:
<Canvas x:Name="CanvasMain" Width="595" Height="842" Background="White" HorizontalAlignment="Center" >
<Rectangle Fill="Tomato" Height="335" Canvas.Left="40" Stroke="Black" Canvas.Top="60" Width="265"/>
<Ellipse Fill="Tomato" Height="175" Canvas.Left="370" Stroke="Black" Canvas.Top="465" Width="200"/>
</Canvas>
I want to set Padding of the Canvas programmatically. Should I set the margin of all the elements inside the Canvas to achieve this purpose or is there any alternative
I want to set Padding of the Canvas programmatically. Should I set the margin of all the elements inside the Canvas to achieve this purpose or is there any alternative
It is either that or adjusting the coordinates (the Canvas.Top and Canvas.Left properties) of the elements.
A Canvas has no concept of padding so you need to create the gap yourself somehow. There is no right or wrong really.
I think you can try to put the canvas in a border.
<Border x:Name="rootBorder">
<Canvas x:Name="CanvasMain" Width="595" Height="842" Background="White" HorizontalAlignment="Center" >
</Canvas>
</Border>
Then you can set border's padding.
rootBorder.Padding = new Thickness(25);

WPF transparent text with opaque background

I need transparent text with opaque background with WPF/XAML. Is that possible?
Here is an example, but I don't use css: css, transparent text with opaque background
Maybe there is a manner in order to produce transparent text with opaque background with c#?
The background should be an Image, I tried it with a Canvas:
<Grid>
<!-- shows only a black box, but should show red text on black background-->
<Canvas Width="100" Height="20" Background="Red"/>
<TextBlock Text="My text" Foreground="#00000000" Background="#FF000000"/>
</Grid>
You can set it using the Opacity property on the SolidColorBrush. It takes values from 0 to 1. Where 0 is complete transparency and 1 complete opacity. But if you set the text transparent then what you will see is the background of the text box. In the example I've set partial opacity so you can see the text is greyish.
<TextBlock Text="Test" Background="Red" Width="100" Height="100">
<TextBlock.Foreground>
<SolidColorBrush Opacity="0.25" Color="Black"/>
</TextBlock.Foreground>
</TextBlock>
Other thing to get the transparency and see the background of the control beneath the text block is to set transparent foreground and partially transparent background.
U can make this by converting your text to Path and then Make Clipping On your white Rectangle with that Path.
Try this:
<Grid Grid.Row="1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<TextBox x:Name="textToMask" TextChanged="textToMask_TextChanged" />
<Rectangle Grid.Row="1" x:Name="target" Fill="Yellow"/>
</Grid>
c# code
private void textToMask_TextChanged(object sender, TextChangedEventArgs e)
{
Typeface face = new Typeface("Candara");
FormattedText tx = new FormattedText(textToMask.Text, Thread.CurrentThread.CurrentUICulture, FlowDirection.LeftToRight, face, 70, Brushes.Black);
Geometry textGeom = tx.BuildGeometry(new Point(0, 0));
Rect boundingRect = new Rect(new Point(-100000, -100000), new Point(100000, 100000));
RectangleGeometry boundingGeom = new RectangleGeometry(boundingRect);
GeometryGroup group = new GeometryGroup();
group.Children.Add(boundingGeom);
group.Children.Add(textGeom);
target.Clip = group;
}

SurfaceInkCanvas scales strokes when painting out of bounds

I have a ScatterView that contains an image over which I should be able to draw.
<s:ScatterView HorizontalAlignment="Center" Margin="0,0,0,0" Name="desk" VerticalAlignment="Center">
<s:ScatterViewItem Width="200" Height="200">
<Grid>
<Image Name="img1" Source="/Resources/Desert.jpg"/>
<Viewbox>
<s:SurfaceInkCanvas Name="cvs1"/>
</Viewbox>
</Grid>
</s:ScatterViewItem>
</s:ScatterView>
I noticed that whenever I draw an ink trail towards the border of the image, the strokes on the ink canvas are scaled down to make room for more stuff. I do not want these strokes to be zoomed out. How can I change this behavior?
Here is a video that shows what's going on.
I figured it out. This behavior is caused by the fact that I hadn't defined a Width and Height on the SurfaceInkCanvas. This should do the trick:
<s:SurfaceInkCanvas Name="cvs1" Width="200" Height="200" />

Zoom and move image with code

I have an image inside a border and I would like to show different parts of the image source in the image box at different times. Specifically, when a certain textbox gets focus, I want to change the image so it zooms to a certain portion of the image content.
Here's the XAML:
<Border BorderBrush="Silver" BorderThickness="1" Grid.Column="5" Height="504"
HorizontalAlignment="Left" Margin="20,116,0,0" Name="border1"
VerticalAlignment="Top" Width="410" ClipToBounds="True">
<Image Height="493" Name="image5" Stretch="Fill" Width="390"
ClipToBounds="True" BindingGroup="{Binding}"
Clip="{Binding ElementName=border1}"
Cursor="Hand" StretchDirection="Both" />
</Border>
For an example, my image source is 2550 x 3320 pixels. I would like the image box to show the source in a rectangle starting at point 1755,300 with width of 650 and height of 230. I do not want to use CloneBitmap to cut that rectangle out and display it because I also have a manual zoom set up for this image where the user can use the mouse wheel to zoom in and out and click & drag to pan the image. I still want to allow that after we zoom to desired area.
UPDATE:
I've tried implementing colinsmith's answer, but whenever I change the scrollviewer's offsets, It chops the image, so if I later move (click and drag to pan) it, it's empty space. I've had this working before with just the image inside the scrollviewer, but now I have an image inside a scrollviewer inside a border. The border is necessary for my zoom and pan as I have it set up now.
My updated XAML:
<Border BorderBrush="Silver" BorderThickness="1" Grid.Column="5" Height="504"
HorizontalAlignment="Left" Margin="20,116,0,0" Name="border1"
VerticalAlignment="Top" Width="410" ClipToBounds="True">
<ScrollViewer x:Name="image5scroll" VerticalScrollBarVisibility="Hidden"
HorizontalScrollBarVisibility="Hidden">
<Image Height="493" Name="image5" Stretch="Fill" Width="390"
ClipToBounds="True" BindingGroup="{Binding}"
Clip="{Binding ElementName=image5scroll}" Cursor="Hand"
StretchDirection="Both" />
</ScrollViewer>
</Border>
And code behind:
public void imageZoom(Element element, int index)
{
if (element.Rectangle.Left - 100 > 0)
{
image5scroll.ScrollToHorizontalOffset(element.Rectangle.Left - 100);
image5scroll.Width = element.Rectangle.Width + 200;
image5scroll.Height = element.Rectangle.Height + 200;
border1.Width = image5scroll.Width;
border1.Height = image5scroll.Height;
image5.Width = image5scroll.Width;
image5.Height = image5scroll.Height;
image5.Stretch = System.Windows.Media.Stretch.None;
}
else
{
image5scroll.ScrollToHorizontalOffset(0);
}
if (element.Rectangle.Top - 100 > 0)
{
image5scroll.ScrollToVerticalOffset(element.Rectangle.Top - 100);
}
else
{
image5scroll.ScrollToVerticalOffset(0);
}
}
You can use a ScrollViewer to wrap your Image...then you can tell the ScrollViewer to go to a vertical and horizontal offset by calling the ScrollToVerticalOffset() and ScrollToHorizontalOffset() methods (as there isn't a property which you can set).
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<Border BorderBrush="Silver" BorderThickness="1" Grid.Column="5" Height="504"
HorizontalAlignment="Left" Margin="20,116,0,0" Name="border1" VerticalAlignment="Top" Width="410">
<ScrollViewer x:Name="image5scroll" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden">
<Image Height="493" Name="image5" Stretch="None" Width="390" BindingGroup="{Binding}"
Cursor="Hand" Source="http://www.noaanews.noaa.gov/stories/images/goes-12-firstimage-large081701.jpg"/>
</ScrollViewer>
</Border>
</Grid>
</Page>
However, if you must be be able to set the position of the ScrollViewer using properties instead of code-behind then a solution is to define an Attached Property which does the calls to ScrollToVerticalOffset/ScrollToHorizontalOffset for you underneath.
http://marlongrech.wordpress.com/2009/09/14/how-to-set-wpf-scrollviewer-verticaloffset-and-horizontal-offset/

How to set Canvas.ZIndex to paint a black panel between the controls?

With the following code I can demonstrate how a black panel with a opacity of 50% is on top of every rectangle:
<Grid>
<Rectangle Fill="Black" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="0.5" Canvas.ZIndex="1"/>
<Rectangle Fill="Red" Width="200" Height="200" Canvas.ZIndex="0"/>
<Grid>
<Rectangle Fill="Blue" Width="100" Height="100" Canvas.ZIndex="0"/>
<Rectangle Fill="Yellow" Width="50" Height="50" Canvas.ZIndex="1"/>
</Grid>
</Grid>
It looks like this:
I would like to have the yellow rectangle above the black panel, but that seems to be impossible.
I can achieve something close by setting the ZIndex of the Grid containing both the Blue and Yellow rectangles to "1". But this would also raise the blue rectangle above the black, and this is a problem.
<Grid>
<Rectangle Fill="Black" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Opacity="0.5" Canvas.ZIndex="1"/>
<Rectangle Fill="Red" Width="200" Height="200" Canvas.ZIndex="0"/>
<Grid Canvas.ZIndex="1">
<Rectangle Fill="Blue" Width="100" Height="100" Canvas.ZIndex="0"/>
<Rectangle Fill="Yellow" Width="50" Height="50" Canvas.ZIndex="1"/>
</Grid>
</Grid>
How do I get only the yellow rectangle above the black?
In my real application I have user controls instead of the rectangles. I like to make a particular control standing out by having everything else covered by the half-black shade.
Many Thanks,
I don't think you'll be able to achieve this with your current arrangement of controls.
There are two levels of controls here, the "Blue" and "Yellow" controls inside the inner grid and then the "Black" and "Red controls together with the inner grid.
The ZIndex works on controls at the same "level" - so you can ensure that the yellow control is on top of the blue, but then at the higher level these are grouped under the inner grid so are treated as a single unit.
The only way this would work is if all your controls were at the same level. If you included a second semi opaque rectangle in the inner grid you could get the yellow to be on top of that but that might end up making other controls too dark.
One approach might be to not use just a simple black rectangle.
Instead use a Path composed of two rectangles. The first rectangle will cover the whole area and the second would just cover the control to be available.
This creates a large rectangle with a hole in it where your target control can show through and accept input.
The down side is working out the rectangle geometry to add to create the hole but that's fairly straight forward.

Categories

Resources