WPF assigning border background from image resource - wpf

I'm trying to simulate a grid inventory system. I have this grid with some rows and cols. I have a resource that is an image. The error I'm getting is:
Cannot implicitly convert type 'System.Windows.Controls.Image' to 'System.Windows.Media.Brush'
If I change my Image cast to ImageBrush then the project compiles but the exe crashes right away.
<Grid x:Name="MasterGrid" Margin="0">
<Grid.Resources>
<Image x:Key="notepad" Source="notepad_16x16.jpg" />
</Grid.Resources>
// create a border and set it's background image
Border border = new Border();
border.Visibility = System.Windows.Visibility.Visible;
var img = (Image)MasterGrid.FindResource("notepad");
border.Background = img;
// add the border to the grid
Grid.SetRow(border, 0);
Grid.SetColumn(border, 1);
Grid.SetRowSpan(border, 1);
Grid.SetColumnSpan(border, 1);
InvGrid.Children.Add(border);

The border.Background is expecting a brush, and you're populating it with an image. You need to create an ImageBrush from the Image resource
border.Background = new ImageBrush((BitmapImage)FindResource("notepad"));
Your image resources should be defined as follows:
<Grid.Resources>
<BitmapImage x:Key="notepad" UriSource="images/notepad_16x16.jpg" />
</Grid.Resources>

<Grid.Background>
<ImageBrush ImageSource="C:\... your path to the image\notepad_16x16.jpg"/>
</Grid.Background>
this works for me without setting borders.

Related

WPF Transform Rectangle in Canvas to Selection in Image

I have a rectangle on a canvas that the user can resize, move and so on to make a selection.
I also have an image the size of the screen behind the canvas (basically a screenshot).
I'd like to translate the selection (the rectangle) in the canvas to a 1:1 selection in the image (I want the image directly behind the rectangle) given I have the rectangle's Canvas.Top, Canvas.Left, Width, Height.
<Grid Name="MainGrid" SnapsToDevicePixels="False" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Image x:Name="MainImage" Stretch="None" RenderOptions.BitmapScalingMode="HighQuality"/>
<Border Background="Black" Opacity="0.4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
<Canvas Name="MainCanvas" Width="{Binding Source={x:Static SystemParameters.PrimaryScreenWidth}}" Height="{Binding Source={x:Static SystemParameters.PrimaryScreenHeight}}" Background="Transparent">
<ContentControl Name="SelectionRect" />
</ContentControl>
</Canvas>
</Grid>
I tried doing this: (MainImage is the image under the canvas)
Rect rect = new Rect(Canvas.GetLeft(SelectionRect), Canvas.GetTop(SelectionRect), SelectionRect.Width, SelectionRect.Height);
Rect from_rect = SelectionRect.TransformToVisual(this).TransformBounds(rect);
BitmapSource cropped_bitmap = new CroppedBitmap(MainImage.Source as BitmapSource,
new Int32Rect((int)from_rect.X, (int)from_rect.Y, (int)from_rect.Width, (int)from_rect.Height));
SelectionRectImageSource = cropped_bitmap;
But the image I get (SelectionRectImageSource) is a moved aside version of the actual pixels behind the selection rectangle.
So basically, I don't understand how these transformations work and how I should use them if at all.
Example:
Thanks a lot!
Dolev.
Looks like you need to correct for the DPI difference between the image (usually 72dpi) and the presentation source (usually 96dpi). Additionally, your first Rect should not be offset by Canvas.Left and Canvas.Top; TransformToVisual will take care of the relative offset for you.
var source = (BitmapSource)MainImage.Source;
var selectionRect = new Rect(SelectionRect.RenderSize);
var sourceRect = SelectionRect.TransformToVisual(MainImage)
.TransformBounds(selectionRect);
var xMultiplier = source.PixelWidth / MainImage.ActualWidth;
var yMultiplier = source.PixelHeight / MainImage.ActualHeight;
sourceRect.Scale(xMultiplier, yMultiplier);
var croppedBitmap = new CroppedBitmap(
source,
new Int32Rect(
(int)sourceRect.X,
(int)sourceRect.Y,
(int)sourceRect.Width,
(int)sourceRect.Height));
SelectionRectImageSource= croppedBitmap;
Depending on where this code resides, you may also need to transform the selection rectangle to MainImage instead of this (as I did).
Also, in case MainImage.Source is smaller than the actual MainImage control, you should probably set the horizontal and vertical alignments of MainImage to Left and Top, respectively, less your translated rectangle end up outside the bounds of the source image. You'll need to clamp the selection rectangle to the dimensions of MainImage too.

how can I set a background image in code?

If I want to set a image as background on a textBox I can use this code in the axml:
<Grid>
<Grid.Background>
<ImageBrush ImageSource="MyImage.jpg" />
</Grid.Background>
<TextBlock Text="Some Text" />
</Grid>
However, I am creating a TextBlock in code, I amtrying this:
TextBox myTextBox = new TextBox();
But in this way I don't know how to access to the ImageBrush property.
Which is the way to add a background in code?
Thank so much.
Provided that MyImage.jpg is a file in the application's current folder, you could write
myTextBox.Background = new ImageBrush(new BitmapImage(new Uri("MyImage.jpg")));
If it's a Resource File, you would have to use a Resource File Pack URI:
myTextBox.Background =
new ImageBrush(new BitmapImage(new Uri("pack://application:,,,/MyImage.jpg")));

How to change Border Background image programmatically

I am creating a media player app in WPF c#.
I am using Media Element to do this.
Anyways, I have used <Border> </Border> to add border some places.
<Border Name="hej1">
<Border.Background>
<ImageBrush ImageSource="Images\music.png" Stretch="None"/>
</Border.Background>
<MediaElement ..../>
</Border>
I want to change the ImageSource to some other picture programmatically, how to do that?
I have tried but no success.
So for every song the image in <ImageBrush ImageSource="Images\music.png" is changed.
Thanks in advance
Shafi
Assign a Name to the ImageBrush:
<ImageBrush x:Name="imageBrush" ImageSource="Images\music.png" Stretch="None"/>
Then use the named member in code:
var filename = #"Images\title.png";
imageBrush.ImageSource = new BitmapImage(new Uri(filename, UriKind.Relative));
Or simply cast the value of the Border's Background property to type ImageBrush:
var imageBrush = (ImageBrush)hej1.Background;
var filename = #"Images\title.png";
imageBrush.ImageSource = new BitmapImage(new Uri(filename, UriKind.Relative));
BitmapImage img = new BitmapImage(new Uri(#"Images\myimage.png"));
ImageBrush image = new ImageBrush();
image.ImageSource = img;
Border.Background =image;

WPF ZoomControl and Adorners

This my first post on stack overflow, I hope I get it right. I am using the ZoomControl from WPF Extensions to display an image with pan and zoom support:
<DockPanel Grid.Row="1" x:Name="canvas">
<Controls:ZoomControl x:Name="zoomControl">
<Canvas x:Name="canvas">
<Image x:Name="imageControl" Stretch="None" />
</Canvas>
</Controls:ZoomControl>
</DockPanel>
When the user selects an image with a bowse dialog, I load that image like so:
bmp = new BitmapImage(new Uri(fileName));
this.imageControul.Source = bmp;
I would like to added rectangles\adorners to specific locations (pixel coordinates) on the image the user loaded based on some image processing.
var r = new Rectangle();
r.StrokeThickness = 5;
r.Stroke = Brushes.Black;
r.Fill = Brushes.Transparent;
r.Width = width;
r.Height = height;
Canvas.SetLeft(r, y);
Canvas.SetTop(r, x);
canvas.Children.Add(r);
However, the rectangles are not placed in the expected locations? Wrong scale and location.
Thanks,
John
I expect the problem is that your Canvas is expanding to fill the space rather than being locked to the rectangle. Have a look with a tool like Snoop and see what the bounding boxes of the two are.
You might be able to fix it with Horizontal and VercticalAlignment on the canvas, set them to anything other than Stretch.
If that doesn't work restructure it like this
<ZoomBox>
<Grid>
<Image/>
<Canvas/>
</Grid>
</ZoomBox>
So the Image and the canvas are grouped by the parent Grid which is being transformed.

How to assign a dynamic imagebrush resource to a stackpanel's background in code?

I currently define the background for a user control like this:
<UserControl.Background>
<ImageBrush ImageSource="{DynamicResource LeftMenuBackgroundImage}" />
</UserControl.Background>
How can I move this to code-behind, e.g.:
PSEUDO-CODE:
StackPanel sp = new StackPanel();
sp.Background = new ImageBrush(DynamicResource.GetResourceName("LeftMenuBackgroundImage"));
allow me to answer this one, got it to work like this:
in code:
StackPanel sp = new StackPanel();
sp.SetResourceReference(StackPanel.BackgroundProperty, "LeftMenuBackgroundImageBrush");
in resources:
<ImageBrush x:Key="LeftMenuBackgroundImageBrush"
ImageSource="{DynamicResource LeftMenuBackgroundImage}"/>
<ImageSource x:Key="LeftMenuBackgroundImage">Images/LeftMenuBackground.jpg</ImageSource>

Resources