I'm creating a simple app for windows 8 that writes me a xml file to documents library.
The problem is when i'm save the file, it saves it on skydrive and i want to save it on c:\Users\pc-name\Documents. I'm using KnownFolders.DocumentsLibrary and updated the manifest to save xml files too, otherwise i couldn't save any file in it.
public static async void XmlSaveFreeChallenge(Challenge currentChallenge)
{
var challenge = new XElement("Challenge");
var docSave = new XDocument(challenge);
challenge.Add(new XAttribute("Name", currentChallenge.Template));
var pontos = new XElement("Type", currentChallenge.Type);
docSave.Descendants("Challenge").FirstOrDefault().Add(pontos);
var folder = KnownFolders.DocumentsLibrary;
var outputStream = await folder.OpenStreamForWriteAsync("CaiMUfiles\\output\\Desafios\\" + currentChallenge.Template + ".xml", CreationCollisionOption.ReplaceExisting);
var ms = new MemoryStream();
docSave.Save(outputStream, SaveOptions.None);
await ms.CopyToAsync(outputStream);
}
The user gets to choose where the Documents library points. See the following option: settings charm -> Change PC Settings -> SkyDrive -> Save documents to SkyDrive by default
I'm not sure if it's possible for your app to override the user's choice there. Even if it is possible, it's probably better to respect the user's choice.
What Isaac McGarvey said is correct nevertheless there might by something that you can do. i did not found a way how to programmatically switch default saving folder for libraries but you still have access to all folders that is included in libraries. The only think is that you need to know absolute path so if you can save the path before then you can use this to get desired folder :
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync("AbsolutePath");
and then you can start enumerating creating or whatever you need. The problem is that if you use for example
List<StorageFolder> folder = await KnownFolders.DocumentsLibrary.GetFoldersAsync();
you wont get folder for Documents and folder for SkyDrive and folder for other linked folders to libraries you will just get all folders that is inside all of these folders in one list which mean you cannot choose where to save file.
I hope this helps a bit.
Related
I am struggling to create my first UWP program in C#. I have run into a problem with reading/writing .rtf files and have not been able to work out a solution nor find one in the forums.
My program is an application for reading and writing a daily journal. The daily journal entries are displayed and edited in a RichEditBox. Next to the RichEditBox is a CalendarDatePicker.
When the CalendarDatePicker value changes, the program creates a file name based on the CalendarDatePicker date. For example, if the CalendarDatePicker's value was 7/22/2018, my program would turn that into the following file name: "2018_7_22.rtf" and then assign that to a string named fileName.
All of the above is working as desired. Here is the problem I am having:
When the value of the CalendarDatePicker changes, the program is supposed to immediately load the .rtf file (if it exists) from storage into the RichEditBox. And, when I press the SAVE button, the program is
supposed to save the RichEditBox contents to storage. Both reading and writing the file is supposed to
use the name derived from the CalendarDatePicker value rather than opening up a picker for either
opening or saving the file.
I have not been able to find any documentation about how to read and write a .rtf file for the RichEditBox without using a picker. I do not want to use a picker because I want that the given journal entry can only be read or written according to the file name that is based on the current value of the CalendarDatePicker.
Here is what I am trying to do:
String filePath = Windows.Storage.ApplicationData.Current.LocalFolder.toString;
// this returns error: "cannot convert method group 'ToString' to non-delegate type string"
String fileName = "2018_22_7.rtf"
// this is an example of a string my program would create according to the CalendarDatePicker's value.
At the end of my question is the code from the RichEditBox documentation. I want do away with the portion that uses the picker and replace the following line:
Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync();
with:
Windows.Storage.StorageFile file = filePath + fileName;
Is it possible to do this or am I forced to use a picker with the RichEditBox?
I will deeply appreciate any help I can get in solving this problem. I am
melting from frustration! Thank you!
Here is the code from the RichEditBox documentation:
private async void SaveButton_Click(object sender, RoutedEventArgs e)
{
Windows.Storage.Pickers.FileSavePicker savePicker = new Windows.Storage.Pickers.FileSavePicker();
savePicker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.DocumentsLibrary;
// Dropdown of file types the user can save the file as
savePicker.FileTypeChoices.Add("Rich Text", new List<string>() { ".rtf" });
// Default file name if the user does not type one in or select a file to replace
savePicker.SuggestedFileName = "New Document";
Windows.Storage.StorageFile file = await savePicker.PickSaveFileAsync();
if (file != null)
{
// Prevent updates to the remote version of the file until we
// finish making changes and call CompleteUpdatesAsync.
Windows.Storage.CachedFileManager.DeferUpdates(file);
// write to file
Windows.Storage.Streams.IRandomAccessStream randAccStream =
await file.OpenAsync(Windows.Storage.FileAccessMode.ReadWrite);
editor.Document.SaveToStream(Windows.UI.Text.TextGetOptions.FormatRtf, randAccStream);
// Let Windows know that we're finished changing the file so the
// other app can update the remote version of the file.
Windows.Storage.Provider.FileUpdateStatus status = await Windows.Storage.CachedFileManager.CompleteUpdatesAsync(file);
if (status != Windows.Storage.Provider.FileUpdateStatus.Complete)
{
Windows.UI.Popups.MessageDialog errorBox =
new Windows.UI.Popups.MessageDialog("File " + file.Name + " couldn't be saved.");
await errorBox.ShowAsync();
}
}
}
Universal Windows Apps (apps) can access certain file system locations by default.
Before window version 17134, if you don't want use a picker to access the file, your UWP app only can access the files in the Application install directory, Application data locations, Removable devices and some Locations that UWP apps can access with specific Capability such as the Music and Pictures Libraries. But you can not write into the Application install directory. In this case, you can try to save the file in above location except the Application install directory. Such as the Application data locations then you can create and get the file using the following code. Please see the File access permissions for more details.
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
//Createa file
StorageFile fileToSave = await localFolder.CreateFileAsync("YourFileName");
//Get file
StorageFile file = await localFolder.GetFileAsync("YourFileName");
If your app target on version 17134 and later, you can access all files that the user has access to using the broadFileSystemAccess Capability, this capability works for APIs in the Windows.Storage namespace, you can get the file using the path as following code, here is a sample.
StorageFolder folder = await StorageFolder.GetFolderFromPathAsync(path);
Directory:
App1
- MainPage.xaml.cs
- Sample.xaml
im trying to do is getting the xaml content from the sample as a string but it doesnt work since it cant find the file:
var x = Path.GetFullPath(#"sample.xaml");
FileStream s = new FileStream(x, FileMode.Open);
How can I fix this?
I haven't tried this give it a try.
Save your file in a location eg (Assets Folder)Now, make sure that the
build action is set to Content.
var storageFile = await StorageFile.GetFileFromApplicationUriAsync(
new Uri("ms-appx:///Assets/youfile.xaml"));
The StorageFile you get is of course read-only, but it can be passed to any API that expects a StorageFile.
If you want to read you can try.
var result = storageFile.OpenReadAsync()
StorageFile Documentation
The source files (.xaml, .cs) are compiled, and in the deployed app they do not exist as physical files, so you can't open them this way.
FileOpenPicker picker = new FileOpenPicker();
picker.ViewMode = PickerViewMode.Thumbnail;
picker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
picker.FileTypeFilter.Add(".txt");
A user chooses a file to open. How can I store/copy/save that file to localstorage for future use, so every time the app opens, it picks automatically that file?
After the user opens the file using the FileOpenPicker you can "cache" access to it using StorageApplicationPermissions API.
Once you have the StorageFile you want to open automatically, you can "cache" your access to it using the following code:
string token = StorageApplicationPermissions.FutureAccessList.Add( file );
What you get back is a string token, which you can save for example in the app settings. Next time the app is opened, you can retrieve the file again using the following code:
StorageFile file =
await StorageApplicationPermissions.FutureAccessList.GetFileAsync(token);
Note that this API has limitation of at most 1000 items stored, so if you expect that more could be added, you will have to ensure the older files are removed otherwise you would not be able to add new files.
There is also alternative - StorageApplicationPermissions.MostRecentlyUsedList which you can use the same way as the FutureAccessList, but it has the advantage of automatically managing the list. It can store up to 25 items, but it is able to automatically remove the oldest ones when not needed anymore.
Also note, that this APIs can cache access not only to files but also to folders (StorageFolder).
Copying the file to AppData folder
If you just want to create a local copy of the picked file, you can copy it to the local folder of the app.
var file = await picker.PickSingleFileAsync();
if ( file != null )
{
await file.CopyAsync( ApplicationData.Current.LocalFolder );
}
StorageFile file = await openPicker.PickSingleFileAsync();
if (file != null)
{
var yourPath = file.Path;
}
but It won't work as you expect. But remember you can't open file from location you (your app) don't have access to.
edit: yeah, I see in comments that I have missed some part of the qestion ;)
the easiest way to store the information for future re-use would be propably to use LocalSettings
https://msdn.microsoft.com/library/windows/apps/windows.storage.applicationdata.localsettings.aspx
(sorry for the link, but there is no use in copying info from there)
You could:
1) Store the file name in your project settings;
YourNameSpace.Properties.Settings.fileToLoad;
2) write the file name in a local file (look at TextWriter namespace);
3) store the file name in your database if your application is data-driven
... and others.
I am presuming here that you're using WinForms or Console app. If you are using a webForm, you would need to store the file name in a cookie so you could attach the right file to the right user before they log in or give you credenstials. For Webforms, then, look into the use of cookies.
Just to add to the above suggestions, following example from Official Microsoft document shows how to Store file for future access:
var openPicker = new FileOpenPicker();
StorageFile file = await openPicker.PickSingleFileAsync();
// Process picked file
if (file != null)
{
// Store file for future access
Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(file);
}
else
{
// The user didn't pick a file
}
I have this piece of code:
string jsonPath = #"Model\Datamodel\UserData.json";
User userItem = JsonConvert.DeserializeObject<User>(user);
User.Add(userItem);
string content = user;
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
var file = await folder.GetFileAsync(jsonPath);
await FileIO.WriteTextAsync(file,content);
Debug.WriteLine(String.Format("DONE"));
The "Done" debug line is written in console but it does not write anything to the file.
I also don't get any errors. When I debug and look at Folder and file I see that they are correctly.
Can anybody help?
You can't write to files in Windows.ApplicationModel.Package.Current.InstalledLocation, you need to use one of the other writeable locations available to you instead. (e.g. ApplicationData.Current.LocalFolder)
If you need to access the content of the file that was shipped with the package, I would suggest copying it to the local folder, and using the copy for read/write access.
creating text file:
var myFile = "test";
var folderUsed = Windows.Storage.ApplicationData.Current.LocalFolder;
var fileOption = Windows.Storage.CreationCollisionOption.ReplaceExisting;
var createdFile = await folderUsed.CreateFileAsync(myFile, fileOption);
writing a string into created text file:
var writeThis = "write this ";
await Windows.Storage.FileIO.WriteTextAsync(createdFile, writeThis);
However, it doesn't specify in which part the text file will be created, I'd like to create it inside the package of my app, not in somewhere else in my computer, is it possible?
And secondly, when I execute the second code again, I'd like my file to be written as "write this write this ", not replace the old file and create another one.
You should use
StorageFolder localFolder = ApplicationData.Current.LocalFolder;
since the other folders such as installation folders are restricted and not allowed for read-write operations. Windows Store apps are pretty restricted in this area.
This link is also useful:
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh758325.aspx
If your files are in the assets folder then you can access them by:
String path = "ms-appx:///Assets/" + Domain + ".txt";
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri(path));
string Value = await FileIO.ReadTextAsync(file);
"However, it doesn't specify in which part the text file will be created, I'd like to create it inside the package of my app, not in somewhere else in my computer, is it possible?"
It's actually 'almost' the only thing possible! your application has explicit access to it's own 'LocalFolder' folder, 'RoamingFolder' location which can be shared between application instances or 'TemporaryFolder' for stuff which gets ditched.
You can save files to thing like pictures library using Windows.Storage.KnownFolders.pictureLibrary if you want, and you can get read only access to your installation folder using 'Windows.ApplicationModel.Package.current.installedLocation' if you so wish.