I am adding images to the WPF stack panel using the C# code. For positioning the images, I am using margin keyword but when I have run the project, a white space for the last image created and push the first image. why?
In the below, I have loaded two images from the same source whit different margins and as you see the first image is covered by the white space from the second image. note that the source Image is a png image and has not any with border.
the code is below(note that I used image control first and then i used the border control and both have the same problem ):
Border newLegBorder =new Border();
BitmapImage casingLegBitmapImage = new BitmapImage(new Uri("images/casingleg.png", UriKind.Relative));
newLegBorder.Background = new ImageBrush(casingLegBitmapImage);
newLegBorder.Width = casingLegBitmapImage.Width;
newLegBorder.Height = casingLegBitmapImage.Height;
newLegBorder.SetValue(Grid.ColumnProperty, 0);
newLegBorder.SetValue(Grid.RowProperty, 0);
newLegBorder.VerticalAlignment = VerticalAlignment.Top;
newLegBorder.Margin = new Thickness(0, 0, 100, 0);
newLegBorder.Width = casingLegBitmapImage.Width;
newLegBorder.Height = casingLegBitmapImage.Height;
schematic.Children.Add(newLegBorder);
Border newLeg2Border = new Border();
BitmapImage casingLeg2BitmapImage = new BitmapImage(new Uri("images/casingleg.png", UriKind.Relative));
newLeg2Border.Background = new ImageBrush(casingLeg2BitmapImage);
newLeg2Border.Width = casingLeg2BitmapImage.Width;
newLeg2Border.Height = casingLeg2BitmapImage.Height;
newLeg2Border.SetValue(Grid.ColumnProperty, 0);
newLeg2Border.SetValue(Grid.RowProperty, 0);
newLeg2Border.VerticalAlignment = VerticalAlignment.Top;
newLeg2Border.Margin = new Thickness(100, 0, 0, 0);
newLeg2Border.Width = casingLeg2BitmapImage.Width;
newLeg2Border.Height = casingLeg2BitmapImage.Height;
schematic.Children.Add(newLeg2Border);
<Window
xmlns="schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerikDocking="clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Docking"
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:Chromes="clr-namespace:Telerik.Windows.Controls.Chromes;assembly=Telerik.Windows.Controls"
xmlns:Primitives="clr-namespace:Telerik.Windows.Controls.Primitives;assembly=Telerik.Windows.Controls.Navigation"
x:Class="imagetoolbox.wellSchematic"
Title="wellSchematic"
Height="402" Width="458">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="236"/>
</Grid.ColumnDefinitions>
<StackPanel x:Name="schematic" HorizontalAlignment="Left" Height="371" VerticalAlignment="Top" Width="214">
</StackPanel>
</Grid>
</Window>
The problem is that the stackpanel will, well, stack all children. The first image is not covered by the second image, they are merely stacked on top of each other.
To position the images you should use the grid directly, combined with margins and alignments.
Play around with the XAML sample below to get the layout you want, and transfer it to codebehind.
<Window
....>
<Grid x:Name="schematic">
<!-- First image will stretch vertically -->
<Image Stretch="Fill" Margin="10,20,0,25" HorizontalAlignment="Left" VerticalAlignment="Top" Width="10">
<Image.Source>
<BitmapImage UriSource="images/casingleg"/>
</Image.Source>
</Image>
<Image Margin="0,30,20,0" HorizontalAlignment="Right" VerticalAlignment="Top" Width="10">
<Image.Source>
<BitmapImage UriSource="images/casingleg"/>
</Image.Source>
</Image>
<Image Margin="40,0,0,10" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="10">
<Image.Source>
<BitmapImage UriSource="images/casingleg"/>
</Image.Source>
</Image>
</Grid>
</Window>
Code-behind for the above sample.
public class WellSchematic : UserControl
{
public WellSchematic()
{
InitializeComponent();
var im1 = CreateImage();
im1.HorizontalAlignment = HorizontalAlignment.Left;
im1.VerticalAlignment = VerticalAlignment.Top;
im1.Margin = new Margin(10,20,0,25);
im1.Stretch = Stretch.Fill;
var im2 = CreateImage();
im2.HorizontalAlignment = HorizontalAlignment.Right;
im2.VerticalAlignment = VerticalAlignment.Top;
im2.Margin = new Margin(0,30,20,0);
var im3 = CreateImage();
im3.HorizontalAlignment = HorizontalAlignment.Left;
im3.VerticalAlignment = VerticalAlignment.Bottom;
im3.Margin = new Margin(40,0,0,10);
// Add more pictures
}
private void CreateImage()
{
var image = new Image();
var bmp = new BitmapImage(new Uri(#"images/casingleg", UriKind.Relative));
image.Source = bmp;
image.Width = bmp.Width;
image.Height = bmp.Height;
schematic.Children.Add(image);
}
}
Related
I was following this article and I got my canvas to be saved, however, I want to extend the code's functionality and save a particular part of my canvas as an image, rather than my entire canvas.
I tried setting the rect.Offset and rect.Location properties but the image is always saved from the upper left corner of my canvas.
Does anyone know how can I achieve my wanted functionality in a similar way?
Thanks!
A simple method would be to use a CroppedBitmap after rendering the whole canvas. You could reuse the same RenderTargetBitmap, if you need multiple images.
RenderTargetBitmap rtb = new RenderTargetBitmap((int)canvas.RenderSize.Width,
(int)canvas.RenderSize.Height, 96d, 96d, System.Windows.Media.PixelFormats.Default);
rtb.Render(canvas);
var crop = new CroppedBitmap(rtb, new Int32Rect(50, 50, 250, 250));
BitmapEncoder pngEncoder = new PngBitmapEncoder();
pngEncoder.Frames.Add(BitmapFrame.Create(crop));
using (var fs = System.IO.File.OpenWrite("logo.png"))
{
pngEncoder.Save(fs);
}
If you want to save to a bitmap object instead of a file, you can use:
using (Stream s = new MemoryStream())
{
pngEncoder.Save(s);
Bitmap myBitmap = new Bitmap(s);
}
I know this is an old question, but it took me a while of searching and trying different answers to come up with something that worked reliably well. So to save some time for those in the future, here is a little service to either save a canvas out to a file, or return an ImageSource for display elsewhere in your application.
It should be made more robust for a production application, additional null and error checking, etc..
public static class RenderVisualService
{
private const double defaultDpi = 96.0;
public static ImageSource RenderToPNGImageSource(Visual targetControl)
{
var renderTargetBitmap = GetRenderTargetBitmapFromControl(targetControl);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
var result = new BitmapImage();
using (var memoryStream = new MemoryStream())
{
encoder.Save(memoryStream);
memoryStream.Seek(0, SeekOrigin.Begin);
result.BeginInit();
result.CacheOption = BitmapCacheOption.OnLoad;
result.StreamSource = memoryStream;
result.EndInit();
}
return result;
}
public static void RenderToPNGFile(Visual targetControl, string filename)
{
var renderTargetBitmap = GetRenderTargetBitmapFromControl(targetControl);
var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderTargetBitmap));
var result = new BitmapImage();
try
{
using (var fileStream = new FileStream(filename, FileMode.Create))
{
encoder.Save(fileStream);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"There was an error saving the file: {ex.Message}");
}
}
private static BitmapSource GetRenderTargetBitmapFromControl(Visual targetControl, double dpi = defaultDpi)
{
if (targetControl == null) return null;
var bounds = VisualTreeHelper.GetDescendantBounds(targetControl);
var renderTargetBitmap = new RenderTargetBitmap((int)(bounds.Width * dpi / 96.0),
(int)(bounds.Height * dpi / 96.0),
dpi,
dpi,
PixelFormats.Pbgra32);
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
{
var visualBrush = new VisualBrush(targetControl);
drawingContext.DrawRectangle(visualBrush, null, new Rect(new Point(), bounds.Size));
}
renderTargetBitmap.Render(drawingVisual);
return renderTargetBitmap;
}
}
And a sample WPF app demonstrating it's use.
MainWindow.xaml
<Window x:Class="CanvasToBitmapDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CanvasToBitmapDemo"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Click="Button_Click" Content="Capture Image" Width="100"/>
<Button Click="Button_Click_1" Content="Save To Disk" Width="100"/>
</StackPanel>
<Canvas x:Name="PART_Canvas" Grid.Row="1" Grid.Column="0">
<Ellipse Canvas.Top="50"
Canvas.Left="60"
Fill="Gold"
Width="250"
Height="250" />
<Polyline Stroke="#FF853D00"
StrokeThickness="10"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round"
Points="110,100 120,97 130,95 140,94 150,95 160,97 170,100" />
<Ellipse Canvas.Top="115"
Canvas.Left="114"
Fill="#FF853D00"
Width="45"
Height="50" />
<Polyline Stroke="#FF853D00"
StrokeThickness="10"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round"
Points="205,120 215,117 225,115 235,114 245,115 255,117 265,120" />
<Ellipse Canvas.Top="120"
Canvas.Left="208"
Fill="#FF853D00"
Width="45"
Height="50" />
<Polyline Stroke="#FF853D00"
StrokeThickness="10"
StrokeEndLineCap="Round"
StrokeStartLineCap="Round"
Points="150,220 160,216 170,215 180,215 190,216 202,218 215,221" />
</Canvas>
<Image x:Name="PART_Image" Grid.Row="1" Grid.Column="1" Stretch="None"/>
</Grid>
And the code behind making the calls into the service.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
PART_Image.Source = RenderVisualService.RenderToPNGImageSource(PART_Canvas);
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
RenderVisualService.RenderToPNGFile(PART_Canvas, "myawesomeimage.png");
}
}
Looking at the link you posted, obviously you can choose the rendered target coordinates here.
RenderTargetBitmap rtb = new RenderTargetBitmap((int)rect.Right,
(int)rect.Bottom, 96d, 96d, System.Windows.Media.PixelFormats.Default);
See if this solution works for you.
Size size = new Size(width, height);
canvas.Measure(size);
canvas.Arrange(new Rect(X, Y, width, height));
//Save Image
...
...
// Revert old position
canvas.Measure(new Size());
In my case, I needed to apply a size constraint for the resulting image, since the images needed to be stored and later used as a small icon.
I was able to scale the image down to a reasonable size using CreateScaledRect below in combination with GetScaledRenderTargetBitmapFromControl (thanks to code from #Andy Stagg's post).
Then, to store the image for later use, I used the SaveImageOfControlToStream method below.
private static Rect CreateScaledRect(Visual targetControl)
{
Rect scaledRect;
var bounds = VisualTreeHelper.GetDescendantBounds(targetControl);
// maintain aspect ratio and make sure scaledRect is at least 64 wide or 64 high
if (bounds.Width < bounds.Height)
{
scaledRect = new Rect(new Point(), new Size(64, bounds.Height / bounds.Width * 64));
}
else
{
scaledRect = new Rect(new Point(), new Size(bounds.Width / bounds.Height * 64, 64));
}
return scaledRect;
}
private static BitmapSource GetScaledRenderTargetBitmapFromControl(Visual targetControl, double dpi = defaultDpi)
{
if (targetControl == null) return null;
// Calling CreateScaledRect here to reduce image size
var bounds = CreateScaledRect(targetControl);
var renderTargetBitmap = new RenderTargetBitmap((int)(bounds.Width * dpi / 96.0),
(int)(bounds.Height * dpi / 96.0),
dpi,
dpi,
PixelFormats.Pbgra32);
var drawingVisual = new DrawingVisual();
using (var drawingContext = drawingVisual.RenderOpen())
{
var visualBrush = new VisualBrush(targetControl);
drawingContext.DrawRectangle(visualBrush, null, new Rect(new Point(), bounds.Size));
}
renderTargetBitmap.Render(drawingVisual);
return renderTargetBitmap;
}
public static void SaveImageOfControlToStream(Stream outputStream, Visual targetControl)
{
var bitmapSource = GetScaledRenderTargetBitmapFromControl(targetControl);
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource ));
encoder.Save(outputStream);
}
I have referred the below thread for combing multiple images as single image in uwp.
Merging multiple Images
But the image is not properly converted from Uri to bitmap images for the tiles downloaded from below link
https://a.tile.openstreetmap.org/0/0/0.png
public MainPage()
{
this.InitializeComponent();
MergeImages();
}
async void MergeImages()
{
byte[] Canvas = new byte[512 * 512 * 4];
Windows.Storage.Streams.IRandomAccessStream random = await Windows.Storage.Streams.RandomAccessStreamReference.CreateFromUri(
new Uri("https://a.tile.openstreetmap.org/1/0/0.png",UriKind.RelativeOrAbsolute)).OpenReadAsync();
Windows.Graphics.Imaging.BitmapDecoder decoder = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(random);
Windows.Graphics.Imaging.PixelDataProvider pixelData = await decoder.GetPixelDataAsync();
byte[] tileImage = pixelData.DetachPixelData();
Canvas = PutOnCanvas(Canvas, tileImage, 0,
0, 256, 256, 512);
InMemoryRandomAccessStream memStream = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(Windows.Graphics.Imaging.BitmapEncoder.PngEncoderId, memStream);
encoder.SetPixelData(
Windows.Graphics.Imaging.BitmapPixelFormat.Bgra8,
Windows.Graphics.Imaging.BitmapAlphaMode.Straight,
512, // pixel width
512, // pixel height
96, // horizontal DPI
96, // vertical DPI
Canvas);
try
{
await encoder.FlushAsync();
var bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(memStream);
image.Source = bitmapImage;
}
catch { }
memStream.Dispose();
}
byte[] PutOnCanvas(byte[] Canvas, byte[] Image, uint x, uint y, uint imageheight, uint imagewidth, uint CanvasWidth)
{
for (uint row = y; row < y + imageheight; row++)
for (uint col = x; col < x + imagewidth; col++)
for (int i = 0; i < 4; i++)
Canvas[(row * CanvasWidth + col) * 4 + i] = Image[((row - y) * imagewidth + (col - x)) * 4 + i];
return Canvas;
}
Sample
Actual Output:
Expected output
I found your previous two threads:
How to avoid the flickering effect when dynamically changes the image source in uwp
How to combine multiple image as single image in UWP
They all aimed to avoid the flickering effect. As I comment in your second thread, the flickering effect is caused by you change the images's source in a short time, if you want to avoid it, you can use the animation to change the images with a progress. Here is a example to use the DoubleAnimation Storyboard to animate Opacity property of the Images stackpanel base on your first thread sample:
MainPage.xaml: I create two storyboard to make the images stackpanel disappear or display and give the disappearStoryboard a disappearStoryboard_Completed event handler.
<Page.Resources>
<Storyboard x:Name="disappearStoryboard" Completed="disappearStoryboard_Completed">
<DoubleAnimation
Storyboard.TargetName="RootStackPanel"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:1"/>
</Storyboard>
<Storyboard x:Name="displayStoryboard">
<DoubleAnimation
Storyboard.TargetName="RootStackPanel"
Storyboard.TargetProperty="Opacity"
From="0.0" To="1.0" Duration="0:0:1"/>
</Storyboard>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Name="RootStackPanel">
<StackPanel Orientation="Horizontal">
<Image x:Name="image1" Height="200" Width="200" Source="ms-appx:///Assets/custom200.png"/>
<Image x:Name="image2" Height="200" Width="200" Source="ms-appx:///Assets/custom201.png"/>
<Image x:Name="image3" Height="200" Width="200" Source="ms-appx:///Assets/custom202.png"/>
<Image x:Name="image4" Height="200" Width="200" Source="ms-appx:///Assets/custom203.png"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image x:Name="image5" Height="200" Width="200" Source="ms-appx:///Assets/custom210.png"/>
<Image x:Name="image6" Height="200" Width="200" Source="ms-appx:///Assets/custom211.png"/>
<Image x:Name="image7" Height="200" Width="200" Source="ms-appx:///Assets/custom212.png"/>
<Image x:Name="image8" Height="200" Width="200" Source="ms-appx:///Assets/custom213.png"/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Image x:Name="image9" Height="200" Width="200" Source="ms-appx:///Assets/custom220.png"/>
<Image x:Name="image10" Height="200" Width="200" Source="ms-appx:///Assets/custom221.png"/>
<Image x:Name="image11" Height="200" Width="200" Source="ms-appx:///Assets/custom222.png"/>
<Image x:Name="image12" Height="200" Width="200" Source="ms-appx:///Assets/custom223.png"/>
</StackPanel>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Horizontal">
<Button Height="50" Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"
Content="ReplaceCustom" x:Name="replaceCustom" Click="replaceCustom_Click" Margin="5"/>
<Button Height="50" Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"
Content="Replace OSM" x:Name="replaceOSM" Click="replace_Click" Margin="5"/>
<Button Height="50" Width="150" HorizontalAlignment="Center" VerticalAlignment="Center"
Content="Replace Tile" x:Name="replaceTile" Click="replaceTile_Click" Margin="5"/>
</StackPanel>
</Grid>
MainPage.xaml.cs: I change the Images' resource in the disappearStoryboard 's disappearStoryboard_Completed event handler.
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
bool replaceButtonClicked, replaceCustomButtonClicked, replaceTileButtonClicked;
private void replace_Click(object sender, RoutedEventArgs e)
{
replaceButtonClicked = true;
disappearStoryboard.Begin();
}
private void replaceCustom_Click(object sender, RoutedEventArgs e)
{
replaceCustomButtonClicked = true;
disappearStoryboard.Begin();
}
private void replaceTile_Click(object sender, RoutedEventArgs e)
{
replaceTileButtonClicked = true;
disappearStoryboard.Begin();
}
private void disappearStoryboard_Completed(object sender, object e)
{
if (replaceButtonClicked)
{
image1.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM200.png",
UriKind.RelativeOrAbsolute));
image2.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM201.png",
UriKind.RelativeOrAbsolute));
image3.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM202.png",
UriKind.RelativeOrAbsolute));
image4.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM203.png",
UriKind.RelativeOrAbsolute));
image5.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM210.png",
UriKind.RelativeOrAbsolute));
image6.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM211.png",
UriKind.RelativeOrAbsolute));
image7.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM212.png",
UriKind.RelativeOrAbsolute));
image8.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM213.png",
UriKind.RelativeOrAbsolute));
image9.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM220.png",
UriKind.RelativeOrAbsolute));
image10.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM221.png",
UriKind.RelativeOrAbsolute));
image11.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM222.png",
UriKind.RelativeOrAbsolute));
image12.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM223.png",
UriKind.RelativeOrAbsolute));
replaceButtonClicked = false;
}
if (replaceCustomButtonClicked)
{
image1.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom200.png",
UriKind.RelativeOrAbsolute));
image2.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom201.png",
UriKind.RelativeOrAbsolute));
image3.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom202.png",
UriKind.RelativeOrAbsolute));
image4.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom203.png",
UriKind.RelativeOrAbsolute));
image5.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom210.png",
UriKind.RelativeOrAbsolute));
image6.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom211.png",
UriKind.RelativeOrAbsolute));
image7.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom212.png",
UriKind.RelativeOrAbsolute));
image8.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom213.png",
UriKind.RelativeOrAbsolute));
image9.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom220.png",
UriKind.RelativeOrAbsolute));
image10.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom221.png",
UriKind.RelativeOrAbsolute));
image11.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom222.png",
UriKind.RelativeOrAbsolute));
image12.Source = new BitmapImage(new Uri("ms-appx:///Assets/custom223.png",
UriKind.RelativeOrAbsolute));
replaceCustomButtonClicked = false;
}
if (replaceTileButtonClicked)
{
image1.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM300.png",
UriKind.RelativeOrAbsolute));
image2.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM301.png",
UriKind.RelativeOrAbsolute));
image3.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM302.png",
UriKind.RelativeOrAbsolute));
image4.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM303.png",
UriKind.RelativeOrAbsolute));
image5.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM304.png",
UriKind.RelativeOrAbsolute));
image6.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM305.png",
UriKind.RelativeOrAbsolute));
image7.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM306.png",
UriKind.RelativeOrAbsolute));
image8.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM301.png",
UriKind.RelativeOrAbsolute));
image9.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM302.png",
UriKind.RelativeOrAbsolute));
image10.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM303.png",
UriKind.RelativeOrAbsolute));
image11.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM310.png",
UriKind.RelativeOrAbsolute));
image12.Source = new BitmapImage(new Uri("ms-appx:///Assets/OSM311.png",
UriKind.RelativeOrAbsolute));
replaceTileButtonClicked = false;
}
displayStoryboard.Begin();
}
}
I have the need to display an image as the content of a CustomMessageBox. I have attempted to set this up as follows, yet no images is displayed, but everything else looks ok.
Image image = new Image();
BitmapImage bmp = new BitmapImage(new Uri("/Assets/image.png", UriKind.Relative));
image.Source = bmp as ImageSource;
CustomMessageBox messageBox = new CustomMessageBox()
{
Caption = "\n" + "Caption",
Message = "\n" + "Message. + "\n",
LeftButtonContent = "left button",
Content = image
};
messageBox.Dismissed += (s1, e1) =>
{
switch (e1.Result)
{
case CustomMessageBoxResult.LeftButton:
MessageBox.Show("left button");
break;
case CustomMessageBoxResult.None:
MessageBox.Show("none");
break;
default:
MessageBox.Show("default");
break;
}
};
messageBox.Show();
You can add a custom UI as the content of the custom message box. I have done it. Here is the code from one of my projects. It has An image and a textBox in side a StackPanel. Here is the method to create the UI.
private StackPanel CreateUI(string imagePath, string username)
{
StackPanel userStack = new StackPanel()
{
Orientation = System.Windows.Controls.Orientation.Horizontal,
HorizontalAlignment = System.Windows.HorizontalAlignment.Left,
Margin = new Thickness(36, 24, 0, 0)
};
Image profilePic = new Image()
{
Source = new BitmapImage(new Uri(imagePath, UriKind.Absolute)),
Name = "imgProfile",
Height = 100,
Width = 100,
Margin = new Thickness(0, 0, 6, 0)
};
TextBlock userName = new TextBlock()
{
Text = username,
Name = "txblkUserName",
Foreground = new SolidColorBrush(Colors.White),
FontSize = 32,
Margin = new Thickness(0, 12, 0, 0)
};
userStack.Children.Add(profilePic);
userStack.Children.Add(userName);
return userStack;
}
And here is how i added it to the CustomMessageBox.
CustomMessageBox msgBox = new CustomMessageBox()
{
Caption = "Your Caption",
Content = this.CreateUI(profilePic, userName),
Message = "Your Message",
LeftButtonContent = "Left Button Content"
};
msgBox.Show();
It works perfectly. Hope this helps :)
** EDIT: If your image is inside your project, then the UriKind should change to Relative.
I dont know about CustomMessageBox but i do know it uses Popup to show messagebox.
you can do that too. This should give you much more freedom.
See here http://developer.nokia.com/community/wiki/How_to_use_Pop-Ups_in_Windows_Phone
in XAML
<Popup Grid.Row="1" x:Name="popup" IsOpen="False" Margin="0, -30,0,0">
<Grid Background="Black" Height="300" Width="480">
<StackPanel>
<TextBlock Text="MsgBox with Image" FontSize="40" Foreground="White" Margin="15 20"></TextBlock>
<StackPanel Orientation="Horizontal">
<TextBlock Text="This is an image -> " FontSize="22" Foreground="White" Margin="15 0 0 20"></TextBlock>
<Image Source="imagepath" Height="45" VerticalAlignment="Top" Margin="0 -10"/>
<TextBlock Text=" in a msgbox " FontSize="22" Foreground="White" Margin="15 0 0 20"></TextBlock>
</StackPanel>
<Button Content="ok" Width="220" Margin="5 40 20 0" HorizontalAlignment="Left" Click="OKButton_Click"/>
</StackPanel>
</Grid>
</Popup>
in your code behind:
this.popup.IsOpen = true; //opens our custom msgbox
if (this.popup.IsOpen == true)
{
scrollviewerCustom.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled; //disables the scrollviewer
this.ApplicationBar.Disable(); //disables the application bar
}
//on click of OK button
private void OKButton_Click(object sender, RoutedEventArgs e)
{
this.popup.IsOpen = false; //closes our msgbox
scrollviewerCustom.VerticalScrollBarVisibility = ScrollBarVisibility.Visible; //enables the scrollviewer
this.ApplicationBar.Enable(); //enables the application bar
}
I am drawing Circle on an WPF window. The problem is that I am unable add Text to the Circle. The code is given below:
public Graphics()
{
InitializeComponent();
StackPanel myStackPanel = new StackPanel();
Ellipse myel = new Ellipse();
SolidColorBrush mscb = new SolidColorBrush();
mscb.Color = Color.FromArgb(255, 255, 0, 0);
myel.Fill = mscb;
myel.StrokeThickness = 2;
myel.Stroke = Brushes.Black;
myel.Width = 100;
myel.Height = 100;
//string str = "hello";
myStackPanel.Children.Add(myel);
this.Content = myStackPanel;
}
Please help me in this regard.
Shapes are simply shapes, if you want to add text then add both the shape and a TextBlock with your text to a common container which lays them on top of each other, e.g. a Grid without rows or columns.
In XAML:
<Grid>
<Ellipse Width="100" .../>
<TextBlock Text="Lorem Ipsum"/>
</Grid>
C#
var grid = new Grid();
grid.Children.Add(new Ellipse { Width = 100, ... });
grid.Children.Add(new TextBlock { Text = "Lorem Ipsum" });
Or you can use direct positioning in a Canvas if you prefer direct control over the draw position:
My sample defines a UI control that draws rectangles with text in it:
XAML:
<UserControl x:Class="DrawOnCanvas"
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"
xmlns:local="clr-namespace:MySample"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<Canvas x:Name="DrawCanvas" Height="30"/>
</Grid>
Code behind:
// You might e.g. call this in the constructor of DrawOnCanvas
internal void DrawRectWithText()
{
var rect = new System.Windows.Shapes.Rectangle();
rect.Stroke = new SolidColorBrush(Colors.Black);
rect.Fill = new SolidColorBrush(Colors.Beige);
rect.Width = 100;
rect.Height = 100;
// Use Canvas's static methods to position the rectangle
Canvas.SetLeft(rect, 100);
Canvas.SetTop(rect, 100);
var text = new TextBlock()
{
Text = task.Title,
};
// Use Canvas's static methods to position the text
Canvas.SetLeft(text, 90);
Canvas.SetTop(text, 90);
// Draw the rectange and the text to my Canvas control.
// DrawCanvas is the name of my Canvas control in the XAML code
DrawCanvas.Children.Add(rect);
DrawCanvas.Children.Add(text);
}
Why does the following C# code not produce the equivalent of my Silverlight code?
XAML
<Border CornerRadius="8" BorderBrush="White" Height="70" BorderThickness="4">
<StackPanel Orientation="Horizontal">
<Border Margin="5,0,0,0" BorderBrush="White" Height="45" Width="45" BorderThickness="2" CornerRadius="2" Background="White">
<Image Source="/Crystal%20Cloud;component/Resources/Images/weapons/swords/sword_0.png" />
</Border>
<StackPanel Margin="10,0,0,0">
<TextBlock Text="Wooden Dagger" FontFamily="Comic Sans MS" />
<TextBlock Text="DPS: 1" FontFamily="Comic Sans MS" FontSize="16" Margin="15,0,0,0" />
</StackPanel>
</StackPanel>
</Border>
C#
private Border CreateListItem(Item item)
{
// Main border
Border itemBorder = new Border();
itemBorder.BorderThickness = new Thickness(4);
itemBorder.CornerRadius = new CornerRadius(8);
itemBorder.BorderBrush = new SolidColorBrush(Colors.White);
itemBorder.Height = 70;
// Main stack panel
StackPanel mainPanel = new StackPanel();
mainPanel.Orientation = Orientation.Horizontal;
itemBorder.Child = mainPanel;
// The item's image border
Border imageBorder = new Border();
imageBorder.Margin = new Thickness(5, 0, 0, 0);
itemBorder.BorderThickness = new Thickness(2);
itemBorder.CornerRadius = new CornerRadius(2);
itemBorder.BorderBrush = new SolidColorBrush(Colors.White);
itemBorder.Background = new SolidColorBrush(Colors.White);
itemBorder.Height = 45;
itemBorder.Width = 45;
mainPanel.Children.Add(imageBorder);
// The item's image
Image image = new Image();
image.Source = new BitmapImage(new Uri("/Crystal%20Cloud;component/Resources/Images/weapons/swords/sword_0.png"));
imageBorder.Child = image;
// The stack panel for the text
StackPanel textPanel = new StackPanel();
textPanel.Margin = new Thickness(10, 0, 0, 0);
mainPanel.Children.Add(textPanel);
// The title text block
TextBlock titleText = new TextBlock();
titleText.Text = "Wooden Dagger";
titleText.FontFamily = new FontFamily("Comic Sans MS");
textPanel.Children.Add(titleText);
// The status text block
TextBlock statusText = new TextBlock();
statusText.Text = "DPS: 1";
statusText.FontFamily = new FontFamily("Comic Sans MS");
statusText.FontSize = 16;
statusText.Margin = new Thickness(15, 0, 0, 0);
textPanel.Children.Add(statusText);
return itemBorder;
}
Erg... just found the bug itemBorder should be changed to imageBorder.