I'm trying to add a image to a togglebutton in WPF - C#. The thing is that the assignment I'm working on can't be made with the use of XAML at all. I've tried to set the Content property to an image, but all I get is a normal togglebutton, which isn't helping my cause at all.
myToggleButton = new ToggleButton();
myImage = new Image();
BitmapImage bmi = new BitmapImage();
bmi.BeginInit();
bmi.UriSource = new Uri("myImageResource.bmp", UriKind.Relative);
bmi.EndInit();
myImage.Source = bmi;
myToggleButton.Content = myImage;
Hope I supplied enough info, if not please ask for more.
Updated #Phil Wright:
When I ad an image like this:
myImage = new Image();
BitmapImage bmi = new BitmapImage();
bmi.BeginInit();
bmi.UriSource = new Uri("myImageResource.bmp", UriKind.Relative);
bmi.EndInit();
myImage.Source = bmi;
it works...
Update #Matt West:
myGrid.Children.add(MyToggleButton); // This gives me an empty ToggleButton
myGrid.Children.add(MyImage); // This gives me an image with content
You are creating a new toggle button but you aren't adding it to anything. The image is getting added to the toggle button but the actual toggle button isn't added as a Child to anything. You either need to add the toggle button in code behind with something like this:
this.AddChild(myToggleButton);
Or if you already have the toggle button defined in XAML with a name of myToggleButton then remove this line from your code above
myToggleButton = new ToggleButton();
As requested here is the code that works for me in its entirety:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid Name="_Root">
</Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var tb = new ToggleButton();
var image = new Image();
BitmapImage bmi = new BitmapImage();
bmi.BeginInit();
bmi.UriSource = new Uri("/Images/6.png", UriKind.Relative);
bmi.EndInit();
image.Source = bmi;
tb.Content = image;
_Root.Children.Add(tb);
}
}
}
Where the image is a resource; as noted before those last two lines make no sense, if you can get the image to display on its own it should also display inside the button.
Are you sure that the provided bitmap resource is able to be located. If not then the image will be empty and so occupy no space and hence the toggle button looks empty.
image of a toggle button can be set like this:
ToggleButton tgb = new ToggleButton();
BitmapImage bmi = new BitmapImage();
bmi.BeginInit();
bmi.UriSource = new Uri("myImageResource.bmp", UriKind.Relative);
bmi.EndInit();
tgb.Content = new Image { Source = bmi };
Related
I've looked all around this site and have yet to find a way to blur an image in XAML. I've tried some functions in C#, but they haven't worked. I'd like to achieve the blurred background image, like in the Audiocloud app (https://store-images.s-microsoft.com/image/apps.28769.9007199266467874.da79334d-0f1c-4851-8e0b-7ee566918b20.0658cd96-487e-4e1f-a330-10fb030aaa22?w=443&h=788&q=60). How would I go about accomplishing this?
Add Microsofts Win2D.uwp NuGet package to your project. (Right click your project in Solution Explorer > "Manage NuGet packages...")
Have this example XAML UI:
<Grid>
<Image x:Name="myBackground" Stretch="UniformToFill" />
<Image x:Name="myImage" Width="360" Height="300" Source="Assets/test.png" Stretch="UniformToFill" ImageOpened="myImage_ImageOpened"/>
</Grid>
Create an Extension Method for UIElement in a static class:
static class Extension
{
public static async Task<IRandomAccessStream>
RenderToRandomAccessStream(this UIElement element)
{
RenderTargetBitmap rtb = new RenderTargetBitmap();
await rtb.RenderAsync(element);
var pixelBuffer = await rtb.GetPixelsAsync();
var pixels = pixelBuffer.ToArray();
var displayInformation = DisplayInformation.GetForCurrentView();
var stream = new InMemoryRandomAccessStream();
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
encoder.SetPixelData(BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Premultiplied,
(uint)rtb.PixelWidth,
(uint)rtb.PixelHeight,
displayInformation.RawDpiX,
displayInformation.RawDpiY,
pixels);
await encoder.FlushAsync();
stream.Seek(0);
return stream;
}
}
Use it. For example in your public sealed partial class MainPage : Page:
private async void BlurThisUI(UIElement sourceElement, Image outputImage)
{
using (var stream = await sourceElement.RenderToRandomAccessStream())
{
var device = new CanvasDevice();
var bitmap = await CanvasBitmap.LoadAsync(device, stream);
var renderer = new CanvasRenderTarget(device,
bitmap.SizeInPixels.Width,
bitmap.SizeInPixels.Height,
bitmap.Dpi);
using (var ds = renderer.CreateDrawingSession())
{
var blur = new GaussianBlurEffect();
blur.BlurAmount = 5.0f;
blur.Source = bitmap;
ds.DrawImage(blur);
}
stream.Seek(0);
await renderer.SaveAsync(stream, CanvasBitmapFileFormat.Png);
BitmapImage image = new BitmapImage();
image.SetSource(stream);
outputImage.Source = image;
}
}
Call it. In this example when the image was opened (see the XAML above: ImageOpened="myImage_ImageOpened"):
private void myImage_ImageOpened(object sender, RoutedEventArgs e)
{
this.BlurThisUI(myImage, myBackground);
}
Credits goes to Nikola Metulev by this tutorial
Note
As you can see, you can not just use this to blur images but also any UIElement (for example a grid with all its containing UI elements like buttons, checkboxes etc.)
all the usings
using System;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading.Tasks;
using Windows.Graphics.Display;
using Windows.Graphics.Imaging;
using Windows.Storage.Streams;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Effects;
This question already has an answer here:
Attach Image/ImageBrush from code behind
(1 answer)
Closed 6 years ago.
I would like to set the background image for a button to an image I have from a URL; but the following code does not work:
var button = new Button();
Image image = new Image();
image.Source = new BitmapImage(new Uri("https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-folder-128.png", UriKind.Absolute));
button = image;
Specifically "button = image" doesn't work, because Button isn't Image type.
How should I set an image to be the background image of a button?
You can accomplish this by using WebClient to first download the image locally before displaying it in the Button control
using (WebClient c = new WebClient())
{
c.DownloadFile("https://cdn4.iconfinder.com/data/icons/ionicons/512/icon-folder-128.png", "D:/image.png");
}
button.Image = Image.FromFile("D:/image.png");
Where D:/image.png is the location you would like to save your image to
Ok, I've got a solution.
var button = new Button();
var image = new ImageBrush();
image.ImageSource = new BitmapImage(new Uri(url, UriKind.Absolute));
button.Background = image;
Here is the code and the image is not showing. If I use the text content it shows up but the image will not. What am I missing?
//Begin btnLine Code.
btnLine = new System.Windows.Controls.Button();
// Create the image element.
Image simpleImage = new Image();
simpleImage.Width = 200;
simpleImage.Margin = new Thickness(5);
// Create source.
BitmapImage bi = new BitmapImage();
// BitmapImage.UriSource must be in a BeginInit/EndInit block.
bi.BeginInit();
bi.UriSource = new Uri(InstallDir+#"\ToolbarImages\line1.jpg",UriKind.RelativeOrAbsolute);
bi.EndInit();
// Set the image source.
simpleImage.Source = bi;
btnLine.Content= bi;//image button Does not work
//btnLine.Content= simpleImage;//image button Does not work
//btnLine.Content= "o-o";//text button Does work
btnLine.Click += btnLine_Click;
chartWindow.MainMenu.Add(btnLine);
Normally it is much easier to do these things in XAML. it is fairly straight forward to set an image to a a local resource. This is a simple version how.
<Grid>
<Button>
<Image Source="ToolbarImages\image1.jpg"/>
</Button>
</Grid>
If you are looking for a dynamic way to do this, you should use a binding on the source image that way you are leveraging the power of wpf.
change
btnLine.Content= bi;
to
btnLine.Content= simpleImage;
I'm creating a custom datepicker, I have a textbox, once clicked it opens a calendar within a popup.
What I want to do is change the size of the popup so it shows my whole calendar, but I can't manage to change it..., I've tried using Height, Width, MinHeight, MinWidth... but it doesn't work, the popup keep showing with a fixed size.
The thing is that my popup's parent property isn't evaluated since it has expression issues (according to debugger), so I'm sure my popup's parent isn't the main screen( say layout grid).
How can I for example make my popup open within a specific context ?
This part of my code isn't XAML, it's C# code only and it looks like:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
namespace CalendarBranch.components
{
public class wpDatePicker:TextBox
{
private CalendarPopup calendar;
private Popup popup;
public wpDatePicker()
{
this.calendar = new CalendarPopup();
this.popup = new Popup();
this.popup.Child = this.calendar;
this.popup.Margin = new Thickness(0);
this.MouseLeftButtonUp += new MouseButtonEventHandler(wpDatePicker_MouseLeftButtonUp);
this.calendar.onDateSelect += new EventHandler(onDateSelected);
this.IsReadOnly = true;
}
protected void wpDatePicker_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
this.popup.Height = this.calendar.Height;
this.popup.Width = this.calendar.Width;
this.popup.HorizontalAlignment = HorizontalAlignment.Center;
this.popup.VerticalAlignment = VerticalAlignment.Center;
this.popup.HorizontalOffset = 0;
this.popup.VerticalOffset = 0;
this.popup.MinHeight = this.calendar.Height;
this.popup.MinWidth = this.calendar.Width;
this.popup.IsOpen = true;
}
private void onDateSelected(Object sender, EventArgs ea) {
this.Text = this.calendar.SelectedValue.ToShortDateString();
this.popup.IsOpen = false;
}
}
}
PS: the class Calendar is simply a UserControl that contains a grid with multiple columns, HyperLinkButtons and TextBlocks, so nothing special.
Thank you in advance guys ;)
Cheers
Miloud B.
Popup control resizes itself to fit the content inside of it. For example, if you set the child of Popup to be StackPanel with width/height set to 100, the popup will be 100x100.
So it's really important to set the sizes not of your popup, but of your inner panel. Try wrapping your content into the stackpanel and assign necessary width/height there.
I need to generate an image dynamically, and after I read the tutorial here I realize i can use all the controls and layouts from WPF to generate my rendering, and then save it as a JPG.
The idea is to use this instead of GDI+, which is quite primitive.
The question is, how to I create a regular dll file that would generate programatically a WPF canvas so then i can add controls to it and then ouput that to an image file. Keep in mind that it would be consumed by an ASP.NET application.
Any ideas somebody?
That example has a good start but I've found it's got a lot of unneeded junk along with it. The main thing is that you don't need to have a separate WPF project.
Here's what to do:
Reference PresentationCore, PresentationFramework and WindowsBase in your web project.
Create a Canvas and other WPF objects programmatically in an STA thread.
Call a few special methods on them to make sure they update outside of the context of a WPF app.
Render them to an image with RenderTargetBitmap.
Shut down the thread's dispatcher.
Set the mime type and output the image with ASP.NET.
To make this more efficient you could re-use the same thread rather than creating a new one for each image. In that case you would only need to clean up the dispatcher when you shut down the thread.
Here's the full working code I have:
using System;
using System.Web;
using System.Threading;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Controls;
using System.Windows.Documents;
public partial class _Default : System.Web.UI.Page
{
private byte[] imageBuffer;
public void Page_Load(object sender, EventArgs e)
{
this.RenderImage();
Response.Clear();
Response.ContentType = #"image/png";
Response.BufferOutput = true;
Response.BinaryWrite(this.imageBuffer);
Response.Flush();
}
public void RenderImage()
{
Thread worker = new Thread(new ThreadStart(this.RenderImageWorker));
worker.SetApartmentState(ApartmentState.STA);
worker.Name = "RenderImageWorker";
worker.Start();
worker.Join();
}
public void RenderImageWorker()
{
Canvas imageCanvas = new Canvas { Width = 600, Height = 200, Background = Brushes.Azure };
TextBlock tb = new TextBlock();
tb.Width = (double)400;
//tb.Height = (double)200;
tb.TextAlignment = TextAlignment.Center;
tb.Inlines.Add(new Run("This is "));
tb.Inlines.Add(new Bold(new Run("bold")));
tb.Inlines.Add(new Run(" text."));
tb.FontSize = 30;
tb.Foreground = Brushes.Blue;
imageCanvas.Children.Add(tb);
// Update layout
imageCanvas.Measure(new Size(imageCanvas.Width, imageCanvas.Height));
imageCanvas.Arrange(new Rect(new Size(imageCanvas.Width, imageCanvas.Height)));
RenderTargetBitmap bitmapRenderer = new RenderTargetBitmap((int)imageCanvas.ActualWidth, (int)imageCanvas.ActualHeight, 96, 96, PixelFormats.Pbgra32);
bitmapRenderer.Render(imageCanvas);
PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(bitmapRenderer));
using (MemoryStream memoryStream = new MemoryStream())
{
png.Save(memoryStream);
this.imageBuffer = memoryStream.ToArray();
}
if (bitmapRenderer.Dispatcher.Thread.IsAlive)
{
bitmapRenderer.Dispatcher.InvokeShutdown();
}
}
}