I would like to use the new Cycle Tile feature available in Windows Phone 8, although I am having trouble creating this dynamically. My issue arises when attempting to set the images for the Cycle Tile, I do not seem to be getting the correct paths for the images. What I have so far is as follows
MainPage.xaml.cs
private void CreateApplicationTile()
{
//App.PictureList.Pictures grabs all of my application images from IsolatedStorage
int count = App.PictureList.Pictures.Count();
int count1 = count - 9;
var cycleImages = new List<Uri>();
if (count > 0)
{
//I only want to add the 9 most recent images if available
for (int i = count; i > count1; i--)
{
int index = i - 1;
if (index > -1)
{
//Set file to type CapturedPicture, which contains the jpg, name, date, etc.
var file = App.PictureList.Pictures[index] as CapturedPicture;
//TilePictureRepository class saves the file (picture) to "Shared/ShellContent/"
//TilePictureRepository.IsolatedStoragePath = "Shared/ShellContent/"
TilePictureRepository.Instance.SaveToLocalStorage(file, TilePictureRepository.IsolatedStoragePath);
}
}
}
// Select the application tile
ShellTile myTile = ShellTile.ActiveTiles.First();
if (myTile != null)
{
Uri[] u = new Uri[9];
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
IEnumerable<string> files = isf.GetFileNames(TilePictureRepository.IsolatedStoragePath + "*").Reverse();
int x = 0;
foreach (string file in files)
{
if (x < 9)
{
u[x] = new Uri("isostore:/Shared/ShellContent/" + file, UriKind.Absolute);
cycleImages.Add(u[x]);
x++;
}
}
}
CycleTileData newTileData = new CycleTileData
{
Title = "Tile Test",
SmallBackgroundImage = new Uri("/Assets/Tiles/Tile_Small_159x159.png", UriKind.Relative),
CycleImages = cycleImages,
};
myTile.Update(newTileData);
}
}
From what I understand, tile images for the Cycle Tile should be saved in the ShellTile directory within IsolatedStorage. To do this, I am using the following class which I quickly modified (I really only am using the SaveToLocalStorage method)
TilePictureRepository.cs
#region Constants
public const string IsolatedStoragePath = "Shared/ShellContent/";
#endregion
#region Fields
private readonly ObservableCollection<Picture> _pictures = new ObservableCollection<Picture>();
#endregion
#region Properties
public ObservableCollection<Picture> Pictures
{
get { return _pictures; }
}
#endregion
#region Singleton Pattern
private TilePictureRepository()
{
LoadAllPicturesFromIsolatedStorage();
}
public static readonly TilePictureRepository Instance = new TilePictureRepository();
#endregion
/// <summary>
/// Saves to local storage
/// This method gets two parameters: the captured picture instance and the name of the pictures folder in the isolated storage
/// </summary>
/// <param name="capturedPicture"></param>
/// <param name="directory"></param>
public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory)
{
//call IsolatedStorageFile.GetUserStoreForApplication to get an isolated storage file
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
//Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists.
isoFile.EnsureDirectory(directory);
//Combine the pictures folder and captured picture file name and use this path to create a new file
string filePath = Path.Combine(directory, capturedPicture.FileName);
using (var fileStream = isoFile.CreateFile(filePath))
{
using (var writer = new BinaryWriter(fileStream))
{
capturedPicture.Serialize(writer);
}
}
}
/// <summary>
/// To load all saved pictures and add them to the pictures list page
/// </summary>
public CapturedPicture LoadFromLocalStorage(string fileName, string directory)
{
//To open the file, add a call to the IsolatedStorageFile.GetUserStoreForApplication
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
//Combine the directory and file name
string filePath = Path.Combine(directory, fileName);
//use the path to open the picture file from the isolated storage by using the IsolatedStorageFile.OpenFile method
using (var fileStream = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
{
//create a BinaryReader instance for deserializing the CapturedPicture instance
using (var reader = new BinaryReader(fileStream))
{
var capturedPicture = new CapturedPicture();
//create a new instance of the type CapturedPicture called CapturedPicture.Deserialize to deserialize the captured picture and return it
capturedPicture.Deserialize(reader);
return capturedPicture;
}
}
}
/// <summary>
/// To load all the pictures at start time
/// </summary>
private void LoadAllPicturesFromIsolatedStorage()
{
//add call to the IsolatedStorageFile.GetUserStoreForApplication to open an isolated storage file
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
//Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists
isoFile.EnsureDirectory(IsolatedStoragePath);
//Call the IsolatedStorageFile.GetFileNames using the pictures directory and *.jpg as a filter to get all saved pictures
var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, "*.jpg"));
//Iterate through all the picture files in the list and load each using the LoadFromLocalStorage you created earlier
foreach (var pictureFile in pictureFiles)
{
var picture = LoadFromLocalStorage(pictureFile, IsolatedStoragePath);
_pictures.Add(picture);
}
}
My result is that as the smallest tile available on the start screen, I see the application tile, while the medium and large tile sizes only show a blank tile (just the accent color and application name).
Related
I would like to scan a directory ("C:/test") and get all files .pdf recursively
I create a provider like this :
IFileProvider provider = new PhysicalFileProvider("C:/test"); // using config in my code and also tried with "C:/test/"
I placed some pdf in directories and subdirectories
There's a file with this path : C:/test/pdf59.pdf
Another with C:/test/testComplexe/pdf59.pdf
Where I try these lines, they all return "NotFoundDirectoryException" :
provider.getDirectoryContents(#"**")
provider.getDirectoryContents(#"*")
provider.getDirectoryContents(#"*.*")
provider.getDirectoryContents(#"**.*")
provider.getDirectoryContents(#"pdf59.pdf")
provider.getDirectoryContents(#"*.pdf")
Exception this line :
provider.getDirectoryContents(#"testComplexe")
How could i query these recursive directories and files ? Thank you
You can write your own recursive function.
var files = new List<IFileInfo>();
GetFiles("C:/Tests", files);
private void GetFiles(string path, ICollection<IFileInfo> files)
{
IFileProvider provider = new PhysicalFileProvider(path);
var contents = provider.GetDirectoryContents("");
foreach (var content in contents)
{
if (!content.IsDirectory && content.Name.ToLower().EndsWith(".pdf"))
{
files.Add(content);
}
else
{
GetFiles(content.PhysicalPath, files);
}
}
}
For my future self (and others) to copy-paste...
public static class Demo
{
public static void FindPdfs()
{
var provider = new PhysicalFileProvider("c:\\temp");
var pdfs = new List<IFileInfo>();
provider.FindFiles(
directory: "/",
match: file => file.Name.EndsWith(".pdf"),
process: pdfs.Add,
recursive: true);
foreach (var pdf in pdfs)
{
using (var stream = pdf.CreateReadStream())
{
// etc...
}
}
}
}
public static class FileProviderExtensions
{
/// <summary>
/// Searches for files matching some <paramref name="match"/>, and invokes <paramref name="process"/> on them.
/// </summary>
/// <param name="provider">File provider</param>
/// <param name="directory">parent directory for the search, a relative path, leading slashes are ignored,
/// use "" or "/" for starting at the root of <paramref name="provider"/></param>
/// <param name="match">the match predicate, if this returns true the file is passed to <paramref name="process"/></param>
/// <param name="process">this action is invoked on <paramref name="match"/>ing files </param>
/// <param name="recursive">if true directories a</param>
/// <returns>the number of files <paramref name="match"/>ed and <paramref name="process"/>ed</returns>
public static int FindFiles(this IFileProvider provider, string directory, Predicate<IFileInfo> match, Action<IFileInfo> process, bool recursive = false)
{
var dirsToSearch = new Stack<string>();
dirsToSearch.Push(directory);
var count = 0;
while (dirsToSearch.Count > 0)
{
var dir = dirsToSearch.Pop();
foreach (var file in provider.GetDirectoryContents(dir))
{
if (file.IsDirectory)
{
if (!recursive)
continue;
var relPath = Path.Join(dir, file.Name);
dirsToSearch.Push(relPath);
}
else
{
if (!match(file))
continue;
process(file);
count++;
}
}
}
return count;
}
}
This is the simplest version if you just want a list of IFileInfo objects. It uses an extension method. Assumes you already have a IFileProvider, such as one that has been injected.
var files = FileProvider.GetRecursiveFiles("/images").ToArray();
using Microsoft.Extensions.FileProviders;
using System.Collections.Generic;
using System.IO;
public static class FileProviderExtensions
{
public static IEnumerable<IFileInfo> GetRecursiveFiles(this IFileProvider fileProvider, string path, bool includeDirectories = true)
{
var directoryContents = fileProvider.GetDirectoryContents(path);
foreach (var file in directoryContents)
{
if (file.IsDirectory)
{
if (includeDirectories)
{
yield return file;
}
// recursively call GetFiles and return each one
// file.Name is the directory name alone (eg. images)
foreach (var f in fileProvider.GetRecursiveFiles(Path.Combine(path, file.Name), includeDirectories))
{
yield return f;
}
}
else
{
// return file
yield return file;
}
}
}
}
To get the content of your root folder ("C:/test/"), use the provider this way :
var contents = provider.getDirectoryContents("")
Then, you have to enumerate results in contents, and do what ever you want with each one.
Documentation : https://learn.microsoft.com/en-us/aspnet/core/fundamentals/file-providers?view=aspnetcore-2.1
I have a powerpoint template with .potx extension, i need to create a copy of the template file, but the created file does not have any content present in it, it is a blank presentation, below is the function i am using to create a destination file using template file.
/// <summary>
/// Creates a copy of the source template file
/// </summary>
/// <param name="sourceFile">sourcce file which has to be copied</param>
/// <param name="destinationFile">destination file where the new file has to be placed.</param>
public static void CreateFileFromTemplate(this string sourceFile, string destinationFile)
{
try
{
//File.Copy(sourceFile, destinationFile, true);
if (System.IO.Path.GetExtension(sourceFile) == ".potx")
{
if (System.IO.Path.GetExtension(destinationFile) == ".potx")
{
PresentationDocument destinationDoc = PresentationDocument.Create(destinationFile, PresentationDocumentType.Presentation);
PresentationPart presentationPart = destinationDoc.AddPresentationPart();
presentationPart.Presentation = new Presentation();
presentationPart.Presentation.Save();
destinationDoc.Close();
//Package destinationPackage = Package.Open(destinationFile, FileMode.Open, FileAccess.ReadWrite);
using (destinationDoc = PresentationDocument.Open(destinationFile, true))
{
Package templatePackage = Package.Open(sourceFile, FileMode.Open);
using (PresentationDocument templateDocument = PresentationDocument.Open(templatePackage))
{
PresentationPart sourcePresPart = templateDocument.PresentationPart;
PresentationPart destinationPresrPart = destinationDoc.PresentationPart;
//var templateSlideCount = templateDocument.CountSlides();
//for (int slides = 1; slides <= templateSlideCount; slides++)
//{
//}
SlidePart sourceSlidePart;
SlidePart destinationSlidePart;
foreach (SlideId slideId in sourcePresPart.Presentation.SlideIdList)
{
//int i=0;
sourceSlidePart = (SlidePart)sourcePresPart.GetPartById(slideId.RelationshipId);
destinationSlidePart = sourceSlidePart.Clone();
SlideIdList slideIdList = destinationPresrPart.Presentation.SlideIdList;
destinationPresrPart.AddPart(destinationSlidePart);
// Save the modified presentation.
destinationPresrPart.Presentation.Save();
}
}
}
}
else
{
throw new FileFormatException("Invalid destination file format, Valid file should have .pptx as extension");
}
}
else
{
throw new FileFormatException("Invalid file format, Valid file should have .potx as extension");
}
}
catch (Exception ex)
{
throw;
}
}
Extension method used to clone a slide
/// <summary>
/// Clones the specified slide.
/// </summary>
/// <param name="sourceSlide">The slide to clone.</param>
/// <returns>Cloned slide.</returns>
public static SlidePart Clone(this SlidePart sourceSlide)
{
// find the presentationPart: makes the API more fluent
var presentationPart = sourceSlide.GetParentParts()
.OfType<PresentationPart>()
.Single();
// clone slide contents
Slide currentSlide = (Slide)sourceSlide.Slide.CloneNode(true);
var slidePartClone = presentationPart.AddNewPart<SlidePart>();
currentSlide.Save(slidePartClone);
// copy layout part
slidePartClone.AddPart(sourceSlide.SlideLayoutPart);
//copy all embedded elements
foreach (ChartPart part in sourceSlide.ChartParts)
{
ChartPart newpart = slidePartClone.AddNewPart<ChartPart>(part.ContentType, sourceSlide.GetIdOfPart(part));
newpart.FeedData(part.GetStream());
newpart.AddNewPart<EmbeddedPackagePart>(part.EmbeddedPackagePart.ContentType, part.GetIdOfPart(part.EmbeddedPackagePart));
newpart.EmbeddedPackagePart.FeedData(part.EmbeddedPackagePart.GetStream());
}
foreach (EmbeddedObjectPart part in sourceSlide.EmbeddedObjectParts)
{
EmbeddedObjectPart newpart = slidePartClone.AddNewPart<EmbeddedObjectPart>(part.ContentType, sourceSlide.GetIdOfPart(part));
newpart.FeedData(part.GetStream());
}
foreach (EmbeddedPackagePart part in sourceSlide.EmbeddedPackageParts)
{
EmbeddedPackagePart newpart = slidePartClone.AddNewPart<EmbeddedPackagePart>(part.ContentType, sourceSlide.GetIdOfPart(part));
newpart.FeedData(part.GetStream());
}
foreach (ImagePart part in sourceSlide.ImageParts)
{
ImagePart newpart = slidePartClone.AddNewPart<ImagePart>(part.ContentType, sourceSlide.GetIdOfPart(part));
newpart.FeedData(part.GetStream());
}
foreach (VmlDrawingPart part in sourceSlide.VmlDrawingParts)
{
VmlDrawingPart newpart = slidePartClone.AddNewPart<VmlDrawingPart>(part.ContentType, sourceSlide.GetIdOfPart(part));
newpart.FeedData(part.GetStream());
}
foreach (UserDefinedTagsPart part in sourceSlide.UserDefinedTagsParts)
{
UserDefinedTagsPart newpart = slidePartClone.AddNewPart<UserDefinedTagsPart>(part.ContentType, sourceSlide.GetIdOfPart(part));
newpart.FeedData(part.GetStream());
}
return slidePartClone;
}
in my main method i have below code which calls these functions to create the ppt
string sourceFilePath =#"C:\TempFolder\template.potx";
string destinationFilePath = #"C:\TempFolder\ClonedFile.potx";
sourceFilePath.CreateFileFromTemplate(destinationFilePath);
but the final created ppt will not have any slides in it,
any help would be appreciated
I posted a similar answer before on saving an excel template to an actual excel document here and you should be able to apply the same logic with a power point template. Instead of the SpreadsheetDocument you will want to use the PresentationDocument and call ChangeDocumentType on it. Something along these lines:
byte[] byteArray = File.ReadAllBytes("C:\\temp\\sa123.potx");
using (MemoryStream stream = new MemoryStream())
{
stream.Write(byteArray, 0, (int)byteArray.Length);
using (PresentationDocument presentationDoc = PresentationDocument.Open(stream, true))
{
// Change from template type to presentation type
presentationDoc.ChangeDocumentType(PresentationDocumentType.Presentation);
}
File.WriteAllBytes("C:\\temp\\sa123.pptx", stream.ToArray());
}
You can then reopen that saved file and do whatever extra stuff you want to it without touching the template file.
I am developing project in C# windows application. I am new to this technology. I declared Image variable in one class and list in another class. I want to retrieve image from Resource folder and store it in list ten times. I wrote code like this but it is returning null.
class clsAddImage
{
public Image m_imgSampleImage;
}
class clsList
{
public List<clsAddImage> lstImage = new List<clsAddImage>();
}
class clsAddImageToList
{
public void AddImgMethod()
{
clsList objlist = new clsList();
int i;
for (i = 0; i < 10; i++)
{
clsAddImage objaddimg = new clsAddImage();
objlist.lstImage.Add(objaddimg);
}
foreach (clsAddImage addimg in objlist.lstImage)
{
string path = "C:\\Users\\c09684\\Documents\\Visual Studio 2010\\Projects\\WindowsFormsAddImage\\WindowsFormsAddImage\\Resources\\Chrysanthemum.jpg";
addimg.m_imgSampleImage = Image.FromFile(path);
}
}
}
public Form1()
{
InitializeComponent();
clsAddImageToList a = new clsAddImageToList();
a.AddImgMethod();
}
I assume that you refer to a Windows8 app? In that case you can not simply program a directory to retrieve information. The user has to choose a directory manually, which you can store for future use. However, you can have access to KnownFolders (for most you have to check Capabilities in the Package.appxmanifest, e.g. Pictures Library), see http://msdn.microsoft.com/en-us/library/windows/apps/windows.storage.knownfolders for the options.
With the following task you will be able to retrieve files from a directory, I hope this helps you solving your problem:
public async Task GetFilesFromDisk()
{
StorageFolder picturesFolder = KnownFolders.PicturesLibrary;
StringBuilder outputText = new StringBuilder();
IReadOnlyList<StorageFile> fileList = await picturesFolder.GetFilesAsync();
var images = new List<BitmapImage>();
if (fileList != null)
{
foreach (StorageFile file in fileList)
{
string cExt = file.FileType;
if (cExt.ToUpper() == ".JPG")
{
Windows.Storage.Streams.IRandomAccessStream fileStream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read);
using (Windows.Storage.Streams.IRandomAccessStream filestream = await file.OpenAsync(Windows.Storage.FileAccessMode.Read))
{
BitmapImage bitmapImage = new BitmapImage();
await bitmapImage.SetSourceAsync(fileStream);
}
}
} // ForEach
}
}
I am allowing a user to delete an item via ContextMenu menu item within the view, and I would like the effect to be seen automatically in the view. As of now, the item in the view remains until the app is restarted, in which case it is then no longer visible. This is very confusing to the user who believes the item has been removed completely from the application. My question is, what am I doing wrong that would fix this issue?
App.xaml.cs
//PictureRepository is a class that gathers pictures from IsolatedStorage
public static PictureRepository PictureList
{
get
{
return PictureRepository.Instance;
}
}
PictureRepository.cs
#region Constants
public const string IsolatedStoragePath = "Pictures";
#endregion
#region Fields
private readonly ObservableCollection<Picture> _pictures = new ObservableCollection<Picture>();
#endregion
#region Properties
public ObservableCollection<Picture> Pictures
{
get { return _pictures; }
}
#endregion
#region Singleton Pattern
private PictureRepository()
{
LoadAllPicturesFromIsolatedStorage();
}
public static readonly PictureRepository Instance = new PictureRepository();
#endregion
/// <summary>
/// Saves to local storage
/// This method gets two parameters: the captured picture instance and the name of the pictures folder in the isolated storage
/// </summary>
/// <param name="capturedPicture"></param>
/// <param name="directory"></param>
public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory)
{
//call IsolatedStorageFile.GetUserStoreForApplication to get an isolated storage file
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
//Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists.
isoFile.EnsureDirectory(directory);
//Combine the pictures folder and captured picture file name and use this path to create a new file
string filePath = Path.Combine(directory, capturedPicture.FileName);
using (var fileStream = isoFile.CreateFile(filePath))
{
using (var writer = new BinaryWriter(fileStream))
{
capturedPicture.Serialize(writer);
}
}
}
/// <summary>
/// To load all saved pictures and add them to the pictures list page
/// </summary>
public CapturedPicture LoadFromLocalStorage(string fileName, string directory)
{
//To open the file, add a call to the IsolatedStorageFile.GetUserStoreForApplication
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
//Combine the directory and file name
string filePath = Path.Combine(directory, fileName);
//use the path to open the picture file from the isolated storage by using the IsolatedStorageFile.OpenFile method
using (var fileStream = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
{
//create a BinaryReader instance for deserializing the CapturedPicture instance
using (var reader = new BinaryReader(fileStream))
{
var capturedPicture = new CapturedPicture();
//create a new instance of the type CapturedPicture called CapturedPicture.Deserialize to deserialize the captured picture and return it
capturedPicture.Deserialize(reader);
return capturedPicture;
}
}
}
/// <summary>
/// To load all the pictures at start time
/// </summary>
private void LoadAllPicturesFromIsolatedStorage()
{
//add call to the IsolatedStorageFile.GetUserStoreForApplication to open an isolated storage file
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
//Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists
isoFile.EnsureDirectory(IsolatedStoragePath);
//Call the IsolatedStorageFile.GetFileNames using the pictures directory and *.jpg as a filter to get all saved pictures
var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, "*.jpg"));
//var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, ""));
//Iterate through all the picture files in the list and load each using the LoadFromLocalStorage you created earlier
foreach (var pictureFile in pictureFiles)
{
var picture = LoadFromLocalStorage(pictureFile, IsolatedStoragePath);
_pictures.Add(picture);
}
}
MainPage.xaml.cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//Recent is the ListBox in the view that is populated from the ObservableCollection
if (Settings.AscendingSort.Value)
{
//Recent.ItemsSource = PictureRepository.Instance.Pictures.OrderBy(x => x.DateTaken);
Recent.ItemsSource = App.PictureList.Pictures.OrderBy(x => x.DateTaken);
}
else
{
//Recent.ItemsSource = PictureRepository.Instance.Pictures.OrderByDescending(x => x.DateTaken);
Recent.ItemsSource = App.PictureList.Pictures.OrderByDescending(x => x.DateTaken);
}
}
//My attempt at deleting the item from both the View and IsolatedStorage
private void deleteContextMenuItem_Click(object sender, RoutedEventArgs e)
{
var listBoxItem = ((MenuItem)sender).DataContext as CapturedPicture;
fileName = listBoxItem.FileName;
if (fileName != null)
{
try
{
//Neither of the following remove the item from the View immediately
App.PictureList.Pictures.Remove(listBoxItem);
PictureRepository.Instance.Pictures.Remove(listBoxItem);
//To open the file, add a call to the IsolatedStorageFile.GetUserStoreForApplication
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
//Combine the directory and file name
string filePath = Path.Combine(PictureRepository.IsolatedStoragePath, fileName);
isoFile.DeleteFile(filePath);
}
catch
{
MessageBoxResult r = MessageBox.Show("There was an error deleting the image.", "Notice", MessageBoxButton.OK);
if (r == MessageBoxResult.OK)
return;
}
}
}
As you can see, I am trying to remove the item from the View and IsolatedStorage. As of now, the removal from IsolatedStorage is working but I cannot seem to get the View to update automatically? I have to wait until the application is restarted and the ListBox is repopulated within the OnNavigatedTo event to see any changes.
The problem is that you are assigning an IOrderedEnumerable to Recent.ItemSource and not a ObservableCollection.
In LoadAllPicturesFromIsolatedStorage() create a temporary List where you add the loaded data from your file and then create the ObservableCollection.
PictureRepository.cs
#region Constants
public const string IsolatedStoragePath = "Pictures";
#endregion
#region Properties
public ObservableCollection<Picture> Pictures
{
get; private set;
}
#endregion
#region Singleton Pattern
private PictureRepository()
{
LoadAllPicturesFromIsolatedStorage();
}
public static readonly PictureRepository Instance = new PictureRepository();
#endregion
/// <summary>
/// Saves to local storage
/// This method gets two parameters: the captured picture instance and the name of the pictures folder in the isolated storage
/// </summary>
/// <param name="capturedPicture"></param>
/// <param name="directory"></param>
public void SaveToLocalStorage(CapturedPicture capturedPicture, string directory)
{
//call IsolatedStorageFile.GetUserStoreForApplication to get an isolated storage file
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
//Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists.
isoFile.EnsureDirectory(directory);
//Combine the pictures folder and captured picture file name and use this path to create a new file
string filePath = Path.Combine(directory, capturedPicture.FileName);
using (var fileStream = isoFile.CreateFile(filePath))
{
using (var writer = new BinaryWriter(fileStream))
{
capturedPicture.Serialize(writer);
}
}
}
/// <summary>
/// To load all saved pictures and add them to the pictures list page
/// </summary>
public CapturedPicture LoadFromLocalStorage(string fileName, string directory)
{
//To open the file, add a call to the IsolatedStorageFile.GetUserStoreForApplication
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
//Combine the directory and file name
string filePath = Path.Combine(directory, fileName);
//use the path to open the picture file from the isolated storage by using the IsolatedStorageFile.OpenFile method
using (var fileStream = isoFile.OpenFile(filePath, FileMode.Open, FileAccess.Read))
{
//create a BinaryReader instance for deserializing the CapturedPicture instance
using (var reader = new BinaryReader(fileStream))
{
var capturedPicture = new CapturedPicture();
//create a new instance of the type CapturedPicture called CapturedPicture.Deserialize to deserialize the captured picture and return it
capturedPicture.Deserialize(reader);
return capturedPicture;
}
}
}
/// <summary>
/// To load all the pictures at start time
/// </summary>
private void LoadAllPicturesFromIsolatedStorage()
{
//add call to the IsolatedStorageFile.GetUserStoreForApplication to open an isolated storage file
var isoFile = IsolatedStorageFile.GetUserStoreForApplication();
//Call the IsolatedStorageFile.EnsureDirectory extension method located in the Common IsolatedStorageFileExtensions class to confirm that the pictures folder exists
isoFile.EnsureDirectory(IsolatedStoragePath);
//Call the IsolatedStorageFile.GetFileNames using the pictures directory and *.jpg as a filter to get all saved pictures
var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, "*.jpg"));
//var pictureFiles = isoFile.GetFileNames(Path.Combine(IsolatedStoragePath, ""));
var pictures = new List<Picture>();
//Iterate through all the picture files in the list and load each using the LoadFromLocalStorage you created earlier
foreach (var pictureFile in pictureFiles)
{
var picture = LoadFromLocalStorage(pictureFile, IsolatedStoragePath);
pictures.Add(picture);
}
Pictures = new ObservableCollection<Picture>(pictures.OrderBy(x => x.DateTaken));
}
On the MainPage.cs change your OnNavigatedTo method to:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//Recent is the ListBox in the view that is populated from the ObservableCollection
//Recent.ItemsSource = PictureRepository.Instance.Pictures.OrderBy(x => x.DateTaken);
Recent.ItemsSource = App.PictureList.Pictures;
}
I have a infopath form that may contain multiple attachments: By using a group of repeating elements, the user can click an “click add item” option he will be able to upload more attachments.
In Sharepoint I am using a workflow to extract the attachments and put them in a separate list. So far I manage only to extract the first one and the workflow finishes successfully.
can I put a loop or something to iterate trough the form?
I attach the code below:
public sealed partial class FileCopyFeature : SharePointSequentialWorkflowActivity
{
public FileCopyFeature()
{
InitializeComponent();
}
public Guid workflowId = default(System.Guid);
public Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties workflowProperties = new Microsoft.SharePoint.Workflow.SPWorkflowActivationProperties();
private void CopyFile(object sender, EventArgs e)
{
// Retrieve the file associated with the item
// on which the workflow has been instantiated
SPFile file = workflowProperties.Item.File;
if (file == null)
return;
// Get the binary data of the file
byte[] xmlFormData = null;
xmlFormData = file.OpenBinary();
// Load the data into an XPathDocument object
XPathDocument ipForm = null;
if (xmlFormData != null)
{
using (MemoryStream ms = new MemoryStream(xmlFormData))
{
ipForm = new XPathDocument(ms);
ms.Close();
}
}
if (ipForm == null)
return;
// Create an XPathNavigator object to navigate the XML
XPathNavigator ipFormNav = ipForm.CreateNavigator();
ipFormNav.MoveToFollowing(XPathNodeType.Element);
XmlNamespaceManager nsManager =
new XmlNamespaceManager(new NameTable());
foreach (KeyValuePair<string, string> ns
in ipFormNav.GetNamespacesInScope(XmlNamespaceScope.All))
{
if (ns.Key == String.Empty)
{
nsManager.AddNamespace("def", ns.Value);
}
else
{
nsManager.AddNamespace(ns.Key, ns.Value);
}
}
do
{
XPathNavigator nodeNav = ipFormNav.SelectSingleNode("//my:field2", nsManager);
// Retrieve the value of the attachment in the InfoPath form
//XPathNavigator nodeNav = ipFormNav.SelectSingleNode(
//"//my:field2", nsManager);
string ipFieldValue = string.Empty;
if (nodeNav != null)
{
ipFieldValue = nodeNav.Value;
// Decode the InfoPath file attachment
InfoPathAttachmentDecoder dec =
new InfoPathAttachmentDecoder(ipFieldValue);
string fileName = dec.Filename;
byte[] data = dec.DecodedAttachment;
// Add the file to a document library
using (SPWeb web = workflowProperties.Web)
{
SPFolder docLib = web.Folders["Doc"];
docLib.Files.Add(fileName, data);
docLib.Update();
// workflowProperties.Item.CopyTo(data + "/Doc/" + fileName);
}
}
}
while (ipFormNav.MoveToNext());
}
}
/// <summary>
/// Decodes a file attachment and saves it to a specified path.
/// </summary>
public class InfoPathAttachmentDecoder
{
private const int SP1Header_Size = 20;
private const int FIXED_HEADER = 16;
private int fileSize;
private int attachmentNameLength;
private string attachmentName;
private byte[] decodedAttachment;
/// <summary>
/// Accepts the Base64 encoded string
/// that is the attachment.
/// </summary>
public InfoPathAttachmentDecoder(string theBase64EncodedString)
{
byte[] theData = Convert.FromBase64String(theBase64EncodedString);
using (MemoryStream ms = new MemoryStream(theData))
{
BinaryReader theReader = new BinaryReader(ms);
DecodeAttachment(theReader);
}
}
private void DecodeAttachment(BinaryReader theReader)
{
//Position the reader to get the file size.
byte[] headerData = new byte[FIXED_HEADER];
headerData = theReader.ReadBytes(headerData.Length);
fileSize = (int)theReader.ReadUInt32();
attachmentNameLength = (int)theReader.ReadUInt32() * 2;
byte[] fileNameBytes = theReader.ReadBytes(attachmentNameLength);
//InfoPath uses UTF8 encoding.
Encoding enc = Encoding.Unicode;
attachmentName = enc.GetString(fileNameBytes, 0, attachmentNameLength - 2);
decodedAttachment = theReader.ReadBytes(fileSize);
}
public void SaveAttachment(string saveLocation)
{
string fullFileName = saveLocation;
if (!fullFileName.EndsWith(Path.DirectorySeparatorChar.ToString()))
{
fullFileName += Path.DirectorySeparatorChar;
}
fullFileName += attachmentName;
if (File.Exists(fullFileName))
File.Delete(fullFileName);
FileStream fs = new FileStream(fullFileName, FileMode.CreateNew);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(decodedAttachment);
bw.Close();
fs.Close();
}
public string Filename
{
get { return attachmentName; }
}
public byte[] DecodedAttachment
{
get { return decodedAttachment; }
}
It appears that your issue has to do with your use of MoveToNext. Per the documentation, this function moves to the next sibling, and does not navigate to children elements. Your code appears to go to the first element it finds (presumably my:myFields), looks for the first child named my:field2 (it only pulls the first one since you are using SelectSingleNode, and then goes to the next sibling of my:myFields (not the next sibling of my:field2). One way to fix this might be to replace your current do-while loop with a call to SelectNodes like the following and then iterate over nodeList.
XmlNodeList nodelist = ipFormNav.SelectNodes("//my:field2", nsManager);