WPF Add a button with image and style dynamically - c#

My objective is as follows: I want to drag drop a file to my WPF window and it should create a button with the icon image at run time.
Currently my code simply creates a button without any image in it. Im new to WPF so please go easy on me!
public static readonly DependencyProperty ImageSourceProperty = DependencyProperty.RegisterAttached("ImageSource", typeof(ImageSource), typeof(AttachedProperties), new UIPropertyMetadata(null));
public static void SetImageSource(DependencyObject d, ImageSource source)
{
d.SetValue(ImageSourceProperty, source);
}
private Bitmap GetIconImageFromFile(String filename)
{
Bitmap bmp = System.Drawing.Icon.ExtractAssociatedIcon(filename).ToBitmap();
bmp.Save("test.bmp");
return bmp;
}
private BitmapImage GetBitmapImageFromBitmap(Bitmap bitmap)
{
BitmapImage bitmapImage = new BitmapImage();
using (MemoryStream memory = new MemoryStream())
{
bitmap.Save(memory, ImageFormat.Png);
memory.Position = 0;
memory.Seek(0, SeekOrigin.Begin);
bitmapImage.BeginInit();
bitmapImage.StreamSource = memory;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
}
return bitmapImage;
}
private void Window_Drop(object sender, System.Windows.DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop) == true)
{
String[] fileNames = (String[])e.Data.GetData(DataFormats.FileDrop);
foreach (String fileName in fileNames)
{
MessageBox.Show("WindowDrop " + fileName);
Button newButton = new Button();
newButton.Width = 100;
newButton.Height = 50;
//newButton.Template = (ControlTemplate)TryFindResource("btemp2");
Bitmap bmp = GetIconImageFromFile(fileName);
BitmapSource src = GetBitmapImageFromBitmap(bmp);
AttachedProperties.SetImageSource(newButton,src);
stack.Children.Add(newButton);
}
}
}

I have modified your code as follows , I create Image instance and set it as button content. Please try this.
foreach (String fileName in fileNames)
{
MessageBox.Show("WindowDrop " + fileName);
Button newButton = new Button();
newButton.Width = 100;
newButton.Height = 50;
//Craete the Image isntance and set the image to be dispalyed
Image ButtonPicture = new Image();
ButtonPicture.BaseUri = fileName;
//Set it to the button content
newButton.Content = ButtonPicture;
AttachedProperties.SetImageSource(newButton,src);
stack.Children.Add(newButton);
}

Related

bitmap loaded memory increase 10x the size of the file

I am loading an image and i get an increase of memory around 10x the size of the file.
this is the output for the code below
Loading file img_6.jpg with originally 513kb
Memory for image img_6.jpg is 63704kb (124.12x)
Thanks!
this is the code i use to load
string filename = "img_6.jpg";
Directory.SetCurrentDirectory(#"C:\Users\Admin\Desktop\isolated images");
Helpers.membefore(filename);
BitmapImage bitmap = new BitmapImage();
//using (Stream stream = new FileStream(filepath, FileMode.Open))
{
bitmap.BeginInit();
//bitmap.StreamSource = stream;
bitmap.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
bitmap.CacheOption = BitmapCacheOption.OnLoad;
bitmap.UriSource = new Uri(filename, UriKind.Relative);
bitmap.EndInit();
}
ImageBrush ib = new ImageBrush() { ImageSource = bitmap };
Helpers.memafter(ib);
these are the memory log helpers
public static void memafter(object result)
{
//debugging
if (result.GetType() == typeof(ImageBrush) && (result as ImageBrush).ImageSource != null)
{
var after = Process.GetCurrentProcess().VirtualMemorySize64;
string factor = ((double)(after - before) / (double)len).ToString("N") ;
string source = (result as ImageBrush).ImageSource.ToString();
Console.WriteLine(String.Format("Memory for image {0} is {1}kb ({2}x)",
source,
(after - before) / 1024,
factor.ToString()));
string s = result.ToString();
}
}
public static void membefore(string xaml)
{
FileInfo fi = new FileInfo(xaml);
len = fi.Length;
Console.WriteLine(string.Format("Loading file {0} with originally {1}kb", xaml, fi.Length / 1024));
if (xaml.Contains("ico") || xaml.Contains("jpg") || xaml.Contains("bmp") || xaml.Contains("png"))
{
before = Process.GetCurrentProcess().VirtualMemorySize64;
}
}
private static long len = 0;
static long before = 0;
Ok right,
the reason there are different file formats was behind it.
Irfanview helped a lot with pressing I opening image information shows file and loaded memory size.

How can I add an image in my database sqlite using dbContext WPF c#?

I want to add an image to the database in an image column in byte form
I am using SQLite to save my database data and WPF Application using dbContext c# to write my code
can anyone help me please?
private void ChooseImageButtonClick(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.Filter = "Choose Image(*.JPG;*.PNG;*.GIF)|*.jpg;*.png;*.gif";
if (dlg.ShowDialog() == true)
{
string FileName = dlg.FileName.ToString();
BitmapImage bitmap = new BitmapImage();
bitmap.BeginInit();
bitmap.UriSource = new Uri(FileName);
bitmap.EndInit();
ImageBox.Source = bitmap;
}
}
private void savebtnClick(object sender, RoutedEventArgs e)
{
using (DatabaseContext dbContext = new DatabaseContext())
{
Person p = new Person
{
Id = int.Parse(Idtextbox.Text),
Name = Nametextbox.Text,
Image = image
};
dbContext.Person.Add(p);
dbContext.SaveChanges();
RefreshList();
}
}
Just convert BitmapImage to byte array first
byte[] image;
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.QualityLevel = 100;
using (MemoryStream ms = new MemoryStream())
{
encoder.Frames.Add(BitmapFrame.Create((BitmapSource)ImageBox.Source));
encoder.Save(ms);
image = ms.ToArray();
}
encoder = null;
And in your database context - add
using (DatabaseContext dbContext = new DatabaseContext())
{
Part part = new Part();
part.Id = int.Parse(TextBoxID.Text);
part.Name = TextBoxName.Text;
part.Image = image;
dbContext.Part.Add(part);
dbContext.SaveChanges();
RefreshPartsList();
}}
To convert byte array back to BitmapImage :
byte[] imageData = part.Image; // that you get from db
if (imageData == null || imageData.Length == 0)
{
//Show error msg or return here;
return;
}
var image = new BitmapImage();
using (var ms = new System.IO.MemoryStream(imageData))
{
image.BeginInit();
image.CacheOption = BitmapCacheOption.OnLoad;
image.StreamSource = ms;
image.EndInit();
image.Freeze();
}
Add Property in 'Part' class
public byte[] ImageCol { get; set; }
Then from "OpenFileDialog" create Image from selected file. For Example
OpenFileDialog openFileDialog = new OpenFileDialog
{
Filter = "Image Files(*.BMP;*.JPG;*.JPEG;*.GIF;*.PNG)|*.BMP;*.JPG;*.JPEG;*.GIF;*.PNG",
InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
};
if (openFileDialog.ShowDialog()==DialogResult.OK)
{
var imageFromFile = System.Drawing.Image.FromFile(openFileDialog.FileName);
part.ImageCol = imageFromFile.ConvertBitmapImagetoBytes();
}
Convert BitMap to byte[]
public static byte[] ConvertBitmapImagetoBytes(this Image image)
{
MemoryStream ms = new MemoryStream();
image.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
return ms.ToArray();
}

WPF passing a button in t a c# function

I have a form that has a lot of buttons in it.
Each button does almost the same thing.
checks a bool to see the state of the button
sends a command based on the state.
changes the background of the button to reflect the state
resets bool to correct state.
private void button_DSK1_LowerThird_Click(object sender, RoutedEventArgs e)
{
if (button_DSK1_LowerThird_Click== false)
{
string newmessage = server.TCPmessage(Vars.ComandSDK1LowerThird);
string dataReturn = server.Connect(Vars.IPAdress, 5250, newmessage);
textBlock_output.Text = dataReturn.ToString();
if (dataReturn.Contains("202"))
{
button_DSK1_LowerThird_State = true;
Uri resourceUri = new Uri("white-glossy-lit.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
button_DSK1_LowerThird.Background = brush;
}
else
{
button_DSK1_LowerThird_State = false;
Uri resourceUri = new Uri("white-glossy-rectangle-button-md.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
button_DSK1_LowerThird.Background = brush;
}
}
else
{
string newmessage = server.TCPmessage("CG 1-20 STOP 1");
string dataReturn = server.Connect(Vars.IPAdress, 5250, newmessage);
textBlock_output.Text = dataReturn.ToString();
if (dataReturn.Contains("202"))
{
button_DSK1_LowerThird_State = false;
Uri resourceUri = new Uri("white-glossy-rectangle-button-md.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
button_DSK1_LowerThird.Background = brush;
}
else
{
button_DSK1_LowerThird_State = true;
Uri resourceUri = new Uri("white-glossy-lit.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
button_DSK1_LowerThird.Background = brush;
}
}
I have all this working correctly. Instead of copying and pasting it a bunch of times I want to move all the code inside of button_DSK1_LowerThird_Click to a function.
I can then call that function and not coppy and paste all the code 25 times.
I can do that. what i can not figure out how to do in the function is.
this line button_DSK1_LowerThird.Background = brush;
what do i need to pass in to the function to replace button_DSK1_LowerThird?
when i call the function i thought, at least in my brain, i could call it like so
ButtonState(string command, Button button, bool state);
then i could have my function check and do every thing that needs to happen for that button.
this is my function as i have it.
public void ButtonState(string command, Button button, bool state)
{
CasparCG server = new CasparCG();
if (state == false)
{
string newmessage = server.TCPmessage(command);
string dataReturn = server.Connect(Vars.IPAdress, 5250, newmessage);
if (dataReturn.Contains("202"))
{
state = true;
Uri resourceUri = new Uri("white-glossy-lit.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
button.Background = brush;
}
else
{
state = false;
Uri resourceUri = new Uri("white-glossy-rectangle-button-md.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
button.Background = brush;
}
}
else
{
string newmessage = server.TCPmessage("CG 1-20 STOP 1");
string dataReturn = server.Connect(Vars.IPAdress, 5250, newmessage);
if (dataReturn.Contains("202"))
{
state = false;
Uri resourceUri = new Uri("white-glossy-rectangle-button-md.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
button.Background = brush;
}
else
{
state = true;
Uri resourceUri = new Uri("white-glossy-lit.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
button.Background = brush;
}
}
i am newer to coding i know there are better ways to do this, i just have not learned them yet.
Have a single click event for all buttons and typecast Sender to button and based on button you can carryout your function.
private void button_Click(object sender, RoutedEventArgs e)
{
if (sender is Button)
{
var btn = sender as Button;
// Here you can carry out your functionality
}
}

Choosing image from windows phone media library and set as page background

I am trying to retrieve an image from the phone library and set it as the page background using the following code
private void selectImageFromMediaLib()
{
selectphoto = new PhotoChooserTask();
selectphoto.Completed += new EventHandler<PhotoResult>(selectphoto_Completed);
selectphoto.Show();
}
private void selectphoto_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
backgroundUri = new Uri(e.OriginalFileName, UriKind.Absolute);
var bitmap = new BitmapImage(backgroundUri);
ImageBrush imageBrush = new ImageBrush();
imageBrush.ImageSource = bitmap;
this.LayoutRoot.Background = imageBrush;
}
}
However, the page background turns black so the photo was not retrieved/created correctly. What is the correct path for the URI to the device library? Isn't using UriKind.Absolute enough?
You can't use the PhotoResult.OriginalFileName property to read the file, instead use the
PhotoResult.ChosenPhoto stream and assign it to the bitmap.ImageSource property in your code.
try this. It works for me
PhotoChooserTask selectphoto;
private void selectImageFromMediaLib()
{
selectphoto = new PhotoChooserTask();
selectphoto.Completed += new EventHandler<PhotoResult>(selectphoto_Completed);
selectphoto.Show();
}
private void selectphoto_Completed(object sender, PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
var imageBytes = new byte[e.ChosenPhoto.Length];
e.ChosenPhoto.Read(imageBytes, 0, imageBytes.Length);
BitmapImage bitmapImage = new BitmapImage();
MemoryStream ms = new MemoryStream(imageBytes);
bitmapImage.SetSource(ms);
ImageBrush imageBrush = new ImageBrush();
imageBrush.ImageSource = bitmapImage;
this.LayoutRoot.Background = imageBrush;
}
}

How can I generate a Image in ScheduledAgent?

I'm unsure on how I can go from WriteAbleBitmap to IconicTileData's url property IconImage.
Here is my code so far:
protected override void OnInvoke(ScheduledTask task)
{
ShellTile tile = ShellTile.ActiveTiles.FirstOrDefault();
if (tile != null)
{
WriteableBitmap genTile = renderTile(202, 202);
tile.Update(new IconicTileData()
{
Title = "IconicTileData",
IconImage = /* PATH TO genTile */
});
}
ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(3));
NotifyComplete();
}
private WriteableBitmap renderTile(int width, int height)
{
Canvas can = new Canvas();
can.Background = new SolidColorBrush(Color.FromArgb(255, 0, 255, 0));
can.Width = width;
can.Height = height;
WriteableBitmap tileImage = new WriteableBitmap(width, height);
tileImage.Render(can, null);
tileImage.Invalidate();
return tileImage;
}
The solution would be to save the file? How can I do that, ShellTile does not share the same space as the application?
Save the file to isolated storage, and then use the "isostore:" prefix in the Uri.
public static void StoreSavedResultImage(string filename, WriteableBitmap wb)
{
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
if (isf.FileExists(filename))
isf.DeleteFile(filename);
using (IsolatedStorageFileStream fs = isf.CreateFile(filename))
{
wb.SaveJpeg(fs, wb.PixelWidth, wb.PixelHeight, 0, 100);
fs.Close();
wb = null;
img = null;
}
}
}
If you want to reference a file from isolated storage in a live tile, the file should be saved in the /Shared/ShellContent folder.
Uri wideUri = new Uri("isostore:/Shared/ShellContent/app_wide.jpg"), UriKind.Absolute);
tile.Update(new IconicTileData()
{
Title = "IconicTileData",
IconImage = wideUri
});

Categories

Resources