Save a picture inside of WPF application - c#

Goal:
- Save a picture from my computer's harddrive to the WPF's application.
- After adding a picture, you are enable to view the picture in visual Studio after updating the solution and projects.
Problem:
I don't know HOW to save a picture inside of my WPF's application. To
be more specificed I want the picture to be saved in the map
ArticlePicture from project DataAccessLibrary.
Again, I know how to do it in ASP.net MVC but not in WPF application. The syntax from MVC doesn't work in WPF application.
Please remember that the picture is not directly from the Internet. I upload the picture directly from my personal computer to the WPF application. The WPF application is stored in my personal PC.
The input data of the picture take place in the project MediaStore
The directory address of the picture is:
"C:\Users\Fullmetalboy\Desktop\Firefox download\picture.gif"
Directory address of the project and its map ArticlePicture is:
"E:\Project\MediaStore\DataAccessLibrary\ArticlePicture\"
The goal is to add and copy the picture to the map "ArticlePicture" with this new address
"E:\Project\MediaStore\DataAccessLibrary\ArticlePicture\picture.gif
I have tried these links but unfortunately, it didn't provide me any success.
http://msdn.microsoft.com/en-us/library/system.windows.media.imaging.bitmapsource.aspx
http://msdn.microsoft.com/en-us/library/ms748873.aspx#_imageformats
Syntax code in WPF application
private void btnBrowse_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.Filter = "jpg files (*.jpg)|*.jpg|gif files (*.gif)|*.gif|jpeg files (*.jpeg)|*.jpeg";
dlg.Multiselect = false;
bool? result = dlg.ShowDialog();
if (result == true)
{
Stream fInfo = dlg.OpenFile();
using (System.Drawing.Image correctPicture = System.Drawing.Image.FromStream(fInfo))
{
if (correctPicture.Width <= 180 && correctPicture.Height <= 250)
{
var fileName = System.IO.Path.GetFileName(dlg.FileName);
var path = System.IO.Path.Combine(Server.MapPath("/Content/Images/"), fileName);
}
else
{
}
}
}
}
Syntax code in ASP.net mVC //
// POST: /Admin/Produkt_ListaCreate/
[HttpPost, Authorize(Roles = "Admin")]
public ActionResult Produkt_ListaCreate(Bok pMyBok, HttpPostedFileBase file)
{
if (file != null)
{
using (System.Drawing.Image correctPicture = System.Drawing.Image.FromStream(file.InputStream))
{
if (correctPicture.Width <= 180 && correctPicture.Height <= 250)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("/Content/Images/"), fileName);
file.SaveAs(path);
pMyBok.BokBildUrl = "/Content/Images/" + fileName;
}
else
{
TempData["message"] = "Den uppladdade bilden fungerar inte pga att den uppfyller inte storlekens och formatets kriterier.";
return RedirectToAction("index");
}
}
} // if (file != null)
_myIBookRepository.Add(pMyBok);
_myIBookRepository.Spara();
TempData["message"] = "En boken är skapad.";
return View("index");
}

Server.MapPath is not going to work in a WPF application - its for IIS applications.
Where does this WPF application run? If its running from the same machine, what directory is it being run from? You need some way for the WPF application to determine where the ArticlePicture directory resides.
Assuming you are running the WPF application from the web server, you know where the directory resides, and the WPF application has permissions to access the directory, then all you need to do is to a file copy operation. (I see no reason to save the file back out of the WPF application if it is not modified).
I suspect maybe your intention is to upload the picture to the website via the WPF application. If so you might need to explain more clearly.

Well first of all, that directory does not exist at runtime as it's compiled into an assembly. You will have to use a folder that exists on disk in which you have sufficient rights to actually right the image data.
I would say you make a folder outside the root of you webapplication in which you can write the pictures. You want this to be outside the root of your web application as you don't want to have your pictures served directly if someone knows the URL I guess.

Related

How to include file in Source Control and edit it later

I'm creating a game using C# and trying to incorporate a CSV for parsing previous scores into a leaderboard and also writing to the file when a player finishes their game.
This is the data stored relating to a score
If this was a sole project I would store the csv in the bin > Debug folder and pass the file path to a StreamReader. Although, this is a group project using Azure Devops/TFS as source control so I'm not too sure what way is best to do this.
I have tried storing the CSV in the Resources of the project but I didn't realise this embeds the file in the project and only allows for reading from the file.
The CSV is currently read like:
var file = Properties.Resources.highscores;
char[] splitter = "\r\n".ToCharArray();
string[] scoresCsv = Properties.Resources.highscores.Split(splitter);
foreach (string score in scoresCsv)
{
if(!String.IsNullOrEmpty(score))
{
var values = score.Split(',');
highScores.Add(new HighScore(values[0], Convert.ToInt32(values[1]), Convert.ToDateTime(values[2])));
}
}
this.highScores = highScores.OrderByDescending(x => x.Score).ToList();
Select the "Team Explorer" window and go to "Source Control Explorer"
Here you will see a global view of the project.
You can add files to your project in any folder you wish outside of the actual source. If you want to you can add your bin folder into the source control and keep that file in the bin folder.
Where-ever you put the file you just need to know the location to it from your project and you are able to map to it and edit it in runtime.
Another option is to create a folder in the C:\ProgramData folder for your game and you can write the leaderboards directly into their C drive when they run the game. People would be able to modify the leaderboards but, obviously the game is for learning purposes of coding and usually you wouldn't store the leaderboards on the client side anyway it would be on a server.
This assumes that the high score data is not shared, and stores it locally. It doesn't require the file to be added to source control.
public class ScoreFileHandler
{
private static string appPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "YourAppName");
private static string scoreFileName = "highscores.txt";
private static string filePath = Path.Combine(appPath, scoreFileName);
public string ReadFile()
{
if (!Directory.Exists(appPath))
{
Directory.CreateDirectory(appPath);
}
if (File.Exists(filePath))
{
return File.ReadAllText(filePath);
}
return string.Empty; // TODO - caller needs to handle this
}
public void WriteFile(string csvScoreData)
{
if (!Directory.Exists(appPath))
{
Directory.CreateDirectory(appPath);
}
File.WriteAllText(filePath, csvScoreData);
}
}

UWP Parse folder from absolute or relative path

I want to parse a folder that the user can choose.
But if I understand, absolute paths are not allowed in UWP because the disks are not the same following the media (xbox, windows phone, windows desktop, ...) ?
So, I have a class called Parser that can parse the path that the user picks but now, only the current folder can be parsed.
This doesn't work :
Parser parser = new Parser(#"C:\a\b\c");
parser.createTreeView(tree);
Help me please. Thank you in advance.
EDIT : This is my Parser class =>
public TreeViewItem Parse(DirectoryInfo directoryInfo)
{
try
{
var directoryNode = new TreeViewItem { Header = directoryInfo.Name };
Convention convention = new Convention();
foreach (var directory in directoryInfo.GetDirectories())
{
directoryNode.Items.Add(Parse(directory));
System.Diagnostics.Debug.WriteLine("test : " + directory.Name);
}
foreach (var file in directoryInfo.GetFiles())
{
if (file.Name.Contains(EConvention.INSTALL))
{
listFiles.Add(file.FullName);
}
TreeViewItem item = new TreeViewItem
{
Header = Path.GetFileNameWithoutExtension(file.FullName),
Tag = file.FullName
};
directoryNode.Items.Add(item);
}
return directoryNode;
}
catch (System.UnauthorizedAccessException e)
{
//MessageDialog dialog = new MessageDialog(""+e.Message);
dialogAsync(e.Message);
return new TreeViewItem();
}
}
public void CreateTreeView(TreeView tree)
{
DirectoryInfo dir = new DirectoryInfo(pathToParse);
System.Diagnostics.Debug.WriteLine("dir exists ? "+dir.Exists);
if (dir.Exists)
{
System.Diagnostics.Debug.WriteLine("dir existe");
TreeViewItem root = new TreeViewItem() { Header = dir.Name };
root.Tag = dir;
tree.Items.Add(Parse(dir));
}
}
UWP apps do not have permission to access all files on the device. Apps can access certain file system locations by default. Apps can also access additional locations through the file picker, or by declaring capabilities. For more info, please see File access permissions
Although, we can use DirectoryInfo in UWP apps, but it can only work with the folders that UWP apps can access by default such as the install directory and local folder etc. Most types in the System.IO namespaces for UWP apps have the similar limitation. While dealing with files or folders in UWP, one important rule is Skip the path: stick to the StorageFile.
You can use a Folder​Picker to let the user choose a folder and then add it to your app's FutureAccessList or MostRecentlyUsedList to keep track of it. You can learn more about using these lists in How to track recently-used files and folders. After this, you will be able to retrieve the StorageFolder from FutureAccessList or MostRecentlyUsedList whenever you want to use it.
Once you have the StorageFolder, you can then use GetFilesAsync() or GetFoldersAsync() method in your Parse instead of DirectoryInfo.GetDirectories or DirectoryInfo.GetFiles method.

Directory.GetDirectories return empty string inside an async Task operation

I have a UWP application which perform to capture and process images from a camera. This project leverage Microsoft Cognitive Services Face Recognition API and I'm exploring the application's existing functionality for awhile now. My goal is that when the image of a person is identified by the camera (through Face Recognition API service), I want to show the associated image of that person.
With that, the images are captured and stored in a local directory of my machine. I want to retrieve the image file and render it on the screen once the person is identified.
The code below shows the async Task method ProcessCameraCapture
private async Task ProcessCameraCapture(ImageAnalyzer e)
{
if (e == null)
{
this.UpdateUIForNoFacesDetected();
this.isProcessingPhoto = false;
return;
}
DateTime start = DateTime.Now;
await e.DetectFacesAsync();
if (e.DetectedFaces.Any())
{
string names;
await e.IdentifyFacesAsync();
this.greetingTextBlock.Text = this.GetGreettingFromFaces(e, out names);
if (e.IdentifiedPersons.Any())
{
this.greetingTextBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.GreenYellow);
this.greetingSymbol.Foreground = new SolidColorBrush(Windows.UI.Colors.GreenYellow);
this.greetingSymbol.Symbol = Symbol.Comment;
GetSavedFilePhoto(names);
}
else
{
this.greetingTextBlock.Foreground = new SolidColorBrush(Windows.UI.Colors.Yellow);
this.greetingSymbol.Foreground = new SolidColorBrush(Windows.UI.Colors.Yellow);
this.greetingSymbol.Symbol = Symbol.View;
}
}
else
{
this.UpdateUIForNoFacesDetected();
}
TimeSpan latency = DateTime.Now - start;
this.faceLantencyDebugText.Text = string.Format("Face API latency: {0}ms", (int)latency.TotalMilliseconds);
this.isProcessingPhoto = false;
}
In GetSavedFilePhoto, I passed the string names argument once the person is identified.
Code below for the GetSavedFilePhoto method
private void GetSavedFilePhoto(string personName)
{
if (string.IsNullOrWhiteSpace(personName)) return;
var directoryPath = #"D:\PersonImages";
var directories = Directory.GetDirectories(directoryPath);
var filePaths = Directory.GetFiles(directoryPath, "*.jpg", SearchOption.AllDirectories);
}
However, in GetSavedFilePhoto method the variable directories returned an empty string of array when using directoryPath string variable. Directory "D:\PersonImages" is a valid and existing folder in my machine and, it contains subfolders with images inside. I also tried Directory.GetFiles to retrieve the jpg images but still returned an empty string.
I think it should work because I have used Directory class several times but not inside an asyncTask method. Does using async caused the files not returned when using I/O operation?
Sorry for this stupid question, but I really don't understand.
Any help is greatly appreciated.
Using Directory.GetFiles or Directory.GetDirectories method can get the folder/file in the local folder of the Application by the following code. But it could not open D:\.
var directories = Directory.GetDirectories(ApplicationData.Current.LocalFolder.Path);
In UWP app you can only access two locations at default (local folder and install folder), others need capabilities setting or file open picker.Details please reference file access permission.
If you need access to all files in D:\, the user must manually pick the D:\ drive using the FolderPicker, then you have permissions to access to files in this drive.
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
picker.SuggestedStartLocation =
Windows.Storage.Pickers.PickerLocationId.ComputerFolder;
picker.FileTypeFilter.Add(".jpg");
picker.FileTypeFilter.Add(".jpeg");
picker.FileTypeFilter.Add(".png");
Windows.Storage.StorageFile file = await picker.PickSingleFileAsync();
if (file != null)
{
// Application now has read/write access to the picked file
}
else
{
//do some stuff
}

Prompt for file on application launch

I am making an application that can potentially be used on multiple computers by the same user. I currently have implemented backup and restore functionality to keep the SQLite database synchronized. However, when I install a new copy of the application, I would like to prompt the user to select a backup file (if applicable).
Initially, I thought that I would just put the logic in MainPageViewModel.xaml in the OnNavigatedTo method. The problem with that is that it would run through that logic every time navigating back to MainView. So, I thought that it would make sense to put it in OnApplicationLaunchAsync to only run once when the application is launched.
Here is my code currently:
private async Task<StorageFile> SelectFileAsync()
{
StorageFile pickedFile = null;
var settings = Container.Resolve<ISettings>();
var picker = new FileOpenPicker();
picker.FileTypeFilter.Add(".sqlite");
picker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
var file = await picker.PickSingleFileAsync();
if (file != null)
{
var pickedFileToken = StorageApplicationPermissions.FutureAccessList.Add(file);
settings.BackupFileToken = pickedFileToken;
pickedFile = file;
}
return pickedFile;
}
protected async override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
var navigationService = Container.Resolve<INavigationService>();
var dialogService = Container.Resolve<IDialogService>();
var settings = Container.Resolve<ISettings>();
if (!string.IsNullOrEmpty(settings.BackupFileToken))
{
var backupFile =
await StorageApplicationPermissions.FutureAccessList.GetFileAsync(settings.BackupFileToken);
var properties = await backupFile.GetBasicPropertiesAsync();
dialogService.Show(string.Format("Backup file found: {0}\r\n" +
"Modified date: {1}", backupFile.Path, properties.DateModified), "");
navigationService.Navigate(Experiences.Main);
}
else
{
navigationService.Navigate(Experiences.Blank);
//dialogService.Show("No backup file specified. Please choose a backup file location.", "");
// TODO: load blank page, then select backup file location, then navigate to main page
await SelectFileAsync();
}
// do not need to return Task.FromResult when OnLaunchApplicationAsync() is async
//return Task.FromResult<object>(null);
}
As you can see, if the BackupFileToken exists, it will check the properties of the file and display a dialog with the file path and last modified date. My problem lies in the situation where it is a new installation/the backup token doesn't exist.
If I try to display a dialog before the FileOpenPicker then the application crashes. I thought perhaps adding a blank view to navigate to, then display the dialog and FileOpenPicker. It just seems like there should be a simpler way to accomplish this (without the need for extra views).
Can someone recommend a way to prompt the user to select a file when the application launches, but let them know the purpose of the FileOpenPicker?
I am aware that my await SelectFileAsync() is losing its return value, this is a temporary situation for testing purposes. I will be sure to assign the return value to the relevant variable once I have found a solution.
Maybe you can use the override
protected override void OnWindowCreated(WindowCreatedEventArgs args) in App.xaml.cs
which is also called once for the creation of the main window.

%AllUsersProfile%(%PROGRAMDATA%) gives a repetitive file path

I have an application written in C#, and I am seeking to write some information to the hidden ProgramData in order to access the same connection string from both the application's front end and back end.
I am accessing the directory using path variables as follows:
private bool ProgramDataWriteFile(string contentToWrite)
{
try
{
string strProgramDataPath = "%PROGRAMDATA%";
string directoryPath = Environment.ExpandEnvironmentVariables(strProgramDataPath) + "\\MyApp\\";
string path = Environment.ExpandEnvironmentVariables(strProgramDataPath)+"\\MyApp\\ConnectionInfo.txt";
if (Directory.Exists(directoryPath))
{
System.IO.StreamWriter file = new System.IO.StreamWriter(path);
file.Write(contentToWrite);
file.Close();
}
else
{
Directory.CreateDirectory(directoryPath);
System.IO.StreamWriter file = new System.IO.StreamWriter(path);
file.Write(contentToWrite);
file.Close();
}
return true;
}
catch (Exception e)
{
}
return false;
}
This seems to work correctly. However, my question is, when I used this path variable: %AllUsersProfile%(%PROGRAMDATA%)
instead, it expanded into an illegal(and redundant) file path : C:\ProgramData(C:\ProgramData)\
However, I thought that the latter path variable was the correct full name. Was I just using it incorrectly? I need to ensure that this connection info will be accessible to all users, will just using %PROGRAMDATA% allow that? I am using Windows 7 in case that is relevant.
From here:
FOLDERID_ProgramData / System.Environment.SpecialFolder.CommonApplicationData
The user would never want to browse here in Explorer, and settings changed here should affect every user on the machine. The default location is %systemdrive%\ProgramData, which is a hidden folder, on an installation of Windows Vista. You'll want to create your directory and set the ACLs you need at install time.
So, just use %PROGRAMDATA%, or better still:
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)

Categories

Resources