I receive an array of messages with attachments from the API and create on their basis Models for UserControls. In model I call Initial method for download image in local storage.But if I open dialog(recieve array from the API) as soon as i run the app, I get an error message System.NotSupportedException in PresentationCore.dll
Additional Information: No pixel format information found.
Here is code of Model:
Most interesting i have catch on it but still get
public class MediaMessageAttachment : ViewModelBase
{
public string FullImageURI { get; set; }
public string VideoURI { get; set; }
public string Title { get; set; }
public bool HasVideo => VideoURI != null;
public bool HasImage => FullImageURI != null;
public string Duration { get; set; }
public bool IsLoading
{
get { return isLoading; }
set
{
isLoading = value;
RaisePropertyChanged("IsLoading");
}
}
private BitmapImage image;
private string previewImageURI;
private bool isLoading;
public string PreviewImageURI { get { return previewImageURI; } set { previewImageURI = value; RaisePropertyChanged("PreviewImageURI"); Initial(); } }
public BitmapImage Image
{
get { return image; }
set
{
image = value;
RaisePropertyChanged("Image");
}
}
public RelayCommand OpenImageCommand
{
get;
private set;
}
public MediaMessageAttachment()
{
OpenImageCommand = new RelayCommand(() => OpenImage());
}
private void OpenImage()
{
if (HasImage)
PopupVM.ShowPopup(FullImageURI);
else if (HasVideo)
PopupVM.ShowPopup(VideoURI);
}
public async Task Initial()
{
IsLoading = true;
if (!Directory.Exists(Environment.CurrentDirectory + "\\temp"))
{
Directory.CreateDirectory(Environment.CurrentDirectory + "\\temp");
}
using (WebClient client = new WebClient())
{
var path = Environment.CurrentDirectory + "\\temp\\" + PreviewImageURI.Substring(PreviewImageURI.LastIndexOf('/') + 1);
if (File.Exists(path))
DownloadFileCompleted(null, null);
else
{
client.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCompleted);
await client.DownloadFileTaskAsync(new Uri(PreviewImageURI), path);
}
}
}
private void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
try
{
var path = Environment.CurrentDirectory + "\\temp\\" + PreviewImageURI.Substring(PreviewImageURI.LastIndexOf('/') + 1);
Image = new BitmapImage();
Image.BeginInit();
Image.UriSource = new Uri(path);
Image.CacheOption = BitmapCacheOption.OnLoad;
Image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
Image.EndInit();
Image.Freeze();
IsLoading = false;
}
catch (System.NotSupportedException)
{
Initial();
}
}
}
Related
There is a parent window, a page is declared in it, there is a (Edit) button on the page. By clicking on the button, a window will open, after it is closed, the data in the parent window should be updated.
ViewModel Parent Window
public class MasterWinViewModel : Notify
{
private object _curentPage;
public object CurentPage
{
get { return _curentPage; }
set
{
_curentPage = value;
SignalChanged("CurentPage");
}
}
public UserApi ProfileUser
{
get => profileUser;
set
{
profileUser = value;
SignalChanged("ProfileUser");
}
}
public CustomCommand Main { get; set; }
public CustomCommand Help { get; set; }
public CustomCommand Search { get; set; }
public CustomCommand MyMediaLibrary { get; set; }
public CustomCommand Profile { get; set; }
public CustomCommand Test { get; set; }
private UserApi profileUser;
public MasterWinViewModel()
{
Task.Run(GetUserId);
Test = new CustomCommand(() =>
{
Test nn = new Test();
nn.Show();
});
Main = new CustomCommand(() =>
{
CurentPage = new MainPage();
SignalChanged("CurentPage");
});
Help = new CustomCommand(() =>
{
CurentPage = new HelpPage();
SignalChanged("CurentPage");
});
Search = new CustomCommand(() =>
{
CurentPage = new SearchPage();
SignalChanged("CurentPage");
});
MyMediaLibrary = new CustomCommand(() =>
{
CurentPage = new MyMediaLibraryPage();
SignalChanged("CurentPage");
});
Profile = new CustomCommand(() =>
{
CurentPage = new ProfilePage();
SignalChanged("CurentPage");
});
}
public async Task GetUserId()
{
Task.Delay(200).Wait();
var t = SingInWindowViewModel.UsId;
var result = await Api.GetAsync<UserApi>(t, "User");
ProfileUser = result;
SignalChanged("ProfileUser");
}
}
ViewModel pages
public class ProfilePageViewModel : Notify
{
private CustomCommand selectedAlbum;
private List<AlbumApi> albums;
public CustomCommand SelectedAlbum
{
get => selectedAlbum;
set
{
selectedAlbum = value;
SignalChanged();
}
}
public List<AlbumApi> Albums
{
get => albums;
set
{
albums = value;
SignalChanged("Albums");
}
}
public CustomCommand NewAlbum { get; set; }
public UserApi ProfileUser { get; set; }
public CustomCommand Edit { get; set; }
public CustomCommand EditAlbum { get; set; }
public CustomCommand DeleteAlbum { get; set; }
public CustomCommand Refresh { get; set; }
public ProfilePageViewModel()
{
Task.Run(GetUserId);
Task.Run(GetAlbumsList);
Refresh = new CustomCommand(() =>
{
Task.Run(GetUserId);
Task.Run(GetAlbumsList);
});
Edit = new CustomCommand(() =>
{
EditUserWindow euw = new EditUserWindow();
euw.ShowDialog();
Thread.Sleep(1000);
Task.Run(GetUserId);
});
NewAlbum = new CustomCommand(() =>
{
AddAlbumWindow albumWindow = new AddAlbumWindow();
albumWindow.Show();
});
}
public async Task GetUserId()
{
var t = SingInWindowViewModel.UsId;
var result = await Api.GetAsync<UserApi>(t, "User");
ProfileUser = result;
SignalChanged("ProfileUser");
}
public async Task GetAlbumsList()
{
var result = await Api.GetListAsync<AlbumApi[]>("Album");
Albums = new List<AlbumApi>(result);
SignalChanged("Albums");
}
public void Load()
{
Task.Run(GetUserId);
Task.Run(GetAlbumsList);
}
}
ViewModel editing windows
public class EditUserWindowViewModel : Notify
{
private BitmapImage image;
public BitmapImage Image
{
get => image;
set
{
image = value;
SignalChanged("Image");
}
}
public UserApi EditUser { get; set; }
public CustomCommand SelectImage { get; set; }
public CustomCommand SaveUser { get; set; }
public EditUserWindowViewModel()
{
Task.Run(GetUserId);
SaveUser = new CustomCommand(() =>
{
Task.Run(EditUsers);
foreach (Window window in Application.Current.Windows)
{
if (window.DataContext == this)
{
CloseWin(window);
}
}
});
string directory = Environment.CurrentDirectory;
SelectImage = new CustomCommand(() =>
{
OpenFileDialog ofd = new OpenFileDialog();
if (ofd.ShowDialog() == true)
{
try
{
var info = new FileInfo(ofd.FileName);
Image = GetImageFromPath(ofd.FileName);
EditUser.Image = $"/Resource/{info.Name}";
var newPath = directory.Substring(0, directory.Length) + EditUser.Image;
if (!File.Exists(newPath))
File.Copy(ofd.FileName, newPath, true);
}
catch (Exception)
{
MessageBox.Show("Code error: Image Error", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
});
}
public void CloseWin(object obj)
{
Window win = obj as Window;
win.Close();
}
private BitmapImage GetImageFromPath(string url)
{
BitmapImage img = new BitmapImage();
img.BeginInit();
img.CacheOption = BitmapCacheOption.OnLoad;
img.UriSource = new Uri(url, UriKind.Absolute);
img.EndInit();
return img;
}
public async Task EditUsers()
{
await Api.PutAsync<UserApi>(EditUser, "User");
}
public async Task GetUserId()
{
var t = SingInWindowViewModel.UsId;
var result = await Api.GetAsync<UserApi>(t, "User");
EditUser = result;
SignalChanged("EditUser");
}
}
I tried to update the data after closing the child window, but this did not solve the problem. Because the child window does not know about the parent window.
I suggest you to use event on each page objects.
Below code is minimum example for it.
ViewModel Parent Window
public class MasterWinViewModel : Notify
{
private object _curentPage;
public object CurentPage
{
get { return _curentPage; }
set
{
_curentPage = value;
SignalChanged("CurentPage");
}
}
public CustomCommand Profile { get; set; }
public MasterWinViewModel()
{
Profile = new CustomCommand(() =>
{
ProfilePageViewModel profilepagevm = new ProfilePageViewModel();
ProfilePageViewModel.OnEventFire += (sender, data) =>
{
//sender = profilepage
//data = data object from profilepage
//Do something with sent data.
}
ProfilePage profilepage = new ProfilePage();
// Set DataContext. Not sure because I don't know ProfilePage's exact implementation.
profilepage.DataContext = profilepagevm;
CurentPage = profilepage;
SignalChanged("CurentPage");
});
}
}
ProfilePageViewModel
public class ProfilePageViewModel : Notify
{
public delegate void EventDelegate(object sender, object data);
public event EventDelegate OnEventFire = null;
public ProfilePageViewModel()
{
}
public void EventFireMethod(object data)
{
//Fire Event
OnEventFire?.Invoke(this, data);
}
}
After calling EventFireMethod in ProfilePage class, callback method will be invoked.
In this way, you can send data between parent window and child page object.
I made an application to download files into a folder inside another folder.
The name for the folder obtained from DataFile name from database and match the name of the image that has been downloaded.
I'm having a problem, that when downloading to a folder for the first bundle of data is fine, but at the time of downloading the data bundle again the previous folder and the new folder also download both files.
When downloading the files that differ it will create a new folder again and the two previous folders are also downloaded the file. For more details, can see in the image below:
And should one folder contains two files.
JSON:
RHData Class:
[PrimaryKey]
public string SKU { get; set; }
public string Judul { get; set; }
public string Tipe { get; set; }
public string Harga { get; set; }
public string Gratis { get; set; }
public string DataFile { get; set; }
RHViewModel class:
class RHViewModel
{
private string sku = string.Empty;
public string SKU
{
get { return sku; }
set
{
if (sku == value)
return;
sku = value;
RaisePropertyChanged("SKU");
}
}
private string judul = string.Empty;
public string Judul
{
get { return judul; }
set
{
if (judul == value)
return;
judul = value;
RaisePropertyChanged("Judul");
}
}
private string tipe = string.Empty;
public string Tipe
{
get { return tipe; }
set
{
if (tipe == value)
return;
tipe = value;
RaisePropertyChanged("Tipe");
}
}
private string harga = string.Empty;
public string Harga
{
get { return harga; }
set
{
if (harga == value)
return;
harga = value;
RaisePropertyChanged("Harga");
}
}
private string cover = string.Empty;
private string gratis = string.Empty;
public string Gratis
{
get { return gratis; }
set
{
if (gratis == value)
return;
gratis = value;
RaisePropertyChanged("Gratis");
}
}
private string dataFile = string.Empty;
public string DataFile
{
get { return dataFile; }
set
{
if (dataFile == value)
return;
dataFile = value;
RaisePropertyChanged("DataFile");
}
}
public RHViewModel GetItem(string itemSku)
{
var item = new RHViewModel();
using (var db = new SQLiteConnection(App.SQLITE_PLATFORM, App.DB_PATH))
{
var _item = (db.Table<RHData>().Where(
c => c.SKU == itemSku)).Single();
item.SKU = _item.SKU;
item.Judul = _item.Judul;
item.Tipe = _item.Tipe;
item.Harga = _item.Harga;
item.Gratis = _item.Gratis;
item.DataFile = _item.DataFile;
}
return item;
}
public string SaveItem(RHViewModel item)
{
string result = string.Empty;
using (var db = new SQLiteConnection(App.SQLITE_PLATFORM, App.DB_PATH))
{
try
{
var existingItem = (db.Table<RHData>().Where(
c => c.SKU == item.sku)).SingleOrDefault();
if (existingItem != null)
{
existingItem.SKU = item.SKU;
existingItem.Judul = item.Judul;
existingItem.Tipe = item.Tipe;
existingItem.Harga = item.Harga;
existingItem.Gratis = item.Gratis;
existingItem.DataFile = item.DataFile;
int success = db.Update(existingItem);
}
else
{
int success = db.Insert(new RHData()
{
SKU = item.SKU,
Judul = item.Judul,
//Deskripsi = item.Deskripsi,
Tipe = item.Tipe,
Harga = item.Harga,
Gratis = item.Gratis,
//Cover = item.Cover,
//File = item.File,
DataFile = item.DataFile
});
}
result = "Success";
}
catch
{
result = "This item was not saved.";
}
}
return result;
}
public string DeleteItem(string itemDataFile)
{
string result = string.Empty;
using (var dbConn = new SQLiteConnection(App.SQLITE_PLATFORM, App.DB_PATH))
{
var existingItem = dbConn.Query<RHData>("select * from RH where DataFile =" + itemDataFile).FirstOrDefault();
if (existingItem != null)
{
dbConn.RunInTransaction(() =>
{
dbConn.Delete(existingItem);
if (dbConn.Delete(existingItem) > 0)
{
result = "Success";
}
else
{
result = "This item was not removed";
}
});
}
return result;
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void RaisePropertyChanged(string propertyName)
{
var handler = this.PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
RHItemsViewModel Class:
class RHItemsViewModel : RHViewModel
{
private ObservableCollection<RHViewModel> items;
public ObservableCollection<RHViewModel> Items
{
get
{
return items;
}
set
{
items = value;
RaisePropertyChanged("Items");
}
}
public ObservableCollection<RHViewModel> GetItems()
{
items = new ObservableCollection<RHViewModel>();
using (var db = new SQLiteConnection(App.SQLITE_PLATFORM, App.DB_PATH))
{
var query = db.Table<RHData>().OrderBy(c => c.SKU);
foreach (var _item in query)
{
var item = new RHViewModel()
{
//SKU = _item.SKU,
SKU = _item.SKU,
Judul = _item.Judul,
//Deskripsi = _item.Deskripsi,
Tipe = _item.Tipe,
Harga = _item.Harga,
Gratis = _item.Gratis,
//Cover = _item.Cover,
//File = _item.File,
DataFile = _item.DataFile
};
items.Add(item);
}
}
return items;
}
}
}
App.Xaml.CS
public static string DB_PATH = Path.Combine(ApplicationData.Current.LocalFolder.Path, "RH.sqlite");
public static SQLite.Net.Platform.WinRT.SQLitePlatformWinRT SQLITE_PLATFORM;
public App()
{
Microsoft.ApplicationInsights.WindowsAppInitializer.InitializeAsync(
Microsoft.ApplicationInsights.WindowsCollectors.Metadata |
Microsoft.ApplicationInsights.WindowsCollectors.Session);
this.InitializeComponent();
this.Suspending += OnSuspending;
SQLITE_PLATFORM = new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT();
if (!CheckFileExists("RH.sqlite").Result)
{
using (var db = new SQLiteConnection(SQLITE_PLATFORM, DB_PATH))
{
db.CreateTable<RHData>();
}
}
}
private async Task<bool> CheckFileExists(string fileName)
{
try
{
var store = await Windows.Storage.ApplicationData.Current.LocalFolder.GetFileAsync(fileName);
return true;
}
catch
{
}
return false;
}
Code:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//GC.Collect();
BukuAudio dlList = e.Parameter as BukuAudio;
if (dlList != null)
{
Queue<DownloadOperation> downloadOperationList = new Queue<DownloadOperation>();
BackgroundDownloader downloader = new BackgroundDownloader();
DownloadProgress.Visibility = Visibility.Visible;
downloadfilename.Visibility = Visibility.Visible;
statusdownload.Visibility = Visibility.Visible;
deleteBtn.Visibility = Visibility.Collapsed;
viewBtn.Visibility = Visibility.Collapsed;
foreach (var path in dlList.BundlePath)
{
DownloadBuku(path);
for (int i = 0; i<dlList.BundlePath.Count;i++)
{
downloadfilename.Text = dlList.BundleName.ElementAt(i);
Uri uri = new Uri(path);
string filename = path.Substring(uri.LocalPath.LastIndexOf("/") + 1);
downloadfilename.Text = String.Format("Unduh '{0}'", filename);
}
}
DownloadGambar(dlList.Cover);
}
else
{
DownloadProgress.Visibility = Visibility.Collapsed;
downloadfilename.Visibility = Visibility.Collapsed;
statusdownload.Visibility = Visibility.Collapsed;
deleteBtn.Visibility = Visibility.Visible;
viewBtn.Visibility = Visibility.Visible;
}
bookAudio = e.Parameter as BookAudio;
}
private async void downloadClicked(object sender, RoutedEventArgs e)
{
Uri uri = new Uri(itemDetail.BundlePath.First());
string filename = System.IO.Path.GetFileName(uri.LocalPath);
string statustext = String.Format("Download Buku '{0}'?", itemDetail.Judul);
string sudahada = String.Format("Buku '{0}' sudah ada/sedang didownload", itemDetail.Judul);
MessageDialog messageDialog;
try
{
StorageFolder library = await ApplicationData.Current.LocalFolder.CreateFolderAsync("library", CreationCollisionOption.OpenIfExists);
var file = await library.GetFileAsync(filename);
messageDialog = new MessageDialog(sudahada, "Buku sudah ada");
messageDialog.Commands.Add(new UICommand("Library", (command) =>
{
this.Frame.Navigate(typeof(library.LibraryPage));
}));
messageDialog.Commands.Add(new UICommand("Batal", (command) =>
{
//rootPage.NotifyUser("The 'Don't install' command has been selected.", NotifyType.StatusMessage);
}));
}
catch (FileNotFoundException ex)
{
//file not exists show download dialog
// Create the message dialog and set its content and title
messageDialog = new MessageDialog(statustext, "Download");
// Add commands and set their callbacks
messageDialog.Commands.Add(new UICommand("Download", (command) =>
{
itemsViewModel = new RHItemsViewModel();
itemsViewModel.SaveItem(new RHViewModel()
{
SKU = itemDetail.SKU.ToString(),
Judul = itemDetail.Judul.ToString(),
Tipe = itemDetail.Tipe.ToString(),
Harga = itemDetail.Harga.ToString(),
Gratis = itemDetail.Gratis.ToString(),
DataFile = itemDetail.DataFile.ToString()
});
this.Frame.Navigate(typeof(library.LibraryPage), itemDetail);
}));
messageDialog.Commands.Add(new UICommand("Batal", (command) =>
{
//rootPage.NotifyUser("The 'Don't install' command has been selected.", NotifyType.StatusMessage);
}));
}
// Show the message dialog
await messageDialog.ShowAsync();
}
}
Library Page:
private async void DownloadBuku(string fileLocation)
{
itemsViewModel = new RHItemsViewModel();
items = new ObservableCollection<RHViewModel>();
using (var dbConn = new SQLiteConnection(App.SQLITE_PLATFORM, App.DB_PATH))
{
var existingItem = dbConn.Table<RHData>().OrderBy(c => c.DataFile);
if (existingItem != null)
{
foreach (var _item in existingItem)
{
var item = new RHViewModel()
{
DataFile = _item.DataFile
};
items.Add(item);
var uri = new Uri(fileLocation);
var downloader = new BackgroundDownloader();
StorageFolder library = await installedLocation.CreateFolderAsync("library", CreationCollisionOption.OpenIfExists);
StorageFolder pdf = await library.CreateFolderAsync(item.DataFile.ToString(), CreationCollisionOption.OpenIfExists);
string filename = System.IO.Path.GetFileName(uri.LocalPath);
StorageFile file = await pdf.CreateFileAsync(filename,
CreationCollisionOption.ReplaceExisting);
DownloadOperation download = downloader.CreateDownload(uri, file);
await StartDownloadAsync(download);
}
}
}
}
BukuAudio Class:
class BukuAudio
{
public string SKU { get; set; }
public string Judul { get; set; }
public string Deskripsi { get; set; }
public string Tipe { get; set; }
public string NamaTipe { get; set; }
public string Harga { get; set; }
public string Cover { get; set; }
public string File { get; set; }
public string Gratis { get; set; }
public string Tanggal { get; set; }
public string DataFile { get; set; }
public JsonArray Bundle_file { get; set; }
public List<string> BundleName { get; set; }
public List<string> BundlePath { get; set; }
}
How to handle it?
Note:
First Bundle File downloaded in the folder "bundle.24b"
Second Bundle file downloaded files in the folder "bundle.23b"
Third Bundle downloaded file in the folder "bundle.22b
Supposedly the file name "bundle.24b ....." downloaded in folder bundle.24b, the file name "bundle.23b ....." downloaded in folder bundle.23b, the file name "bundle.22b ....." downloaded in folder bundle.22b
I have huge problem with saveing and restore ObservableCollection to IsolatedData.
I'm trying with this code.
Helper class for Observable
public class ListItem {
public String Title { get; set; }
public bool Checked { get; set; }
public ListItem(String title, bool isChecked=false) {
Title = title;
Checked = isChecked;
}
private ListItem() { }
}
IsoHelper
public class IsoStoreHelper {
private static IsolatedStorageFile _isoStore;
public static IsolatedStorageFile IsoStore {
get { return _isoStore ?? (_isoStore = IsolatedStorageFile.GetUserStoreForApplication()); }
}
public static void SaveList<T>(string folderName, string dataName, ObservableCollection<T> dataList) where T : class {
if (!IsoStore.DirectoryExists(folderName)) {
IsoStore.CreateDirectory(folderName);
}
if (IsoStore.FileExists(folderName + "\\" + dataName+".dat")) {
IsoStore.DeleteFile(folderName + "\\" + dataName + ".dat");
}
string fileStreamName = string.Format("{0}\\{1}.dat", folderName, dataName);
try {
using (var stream = new IsolatedStorageFileStream(fileStreamName, FileMode.Create, IsoStore)) {
var dcs = new DataContractSerializer(typeof(ObservableCollection<T>));
dcs.WriteObject(stream, dataList);
}
} catch (Exception e) {
Debug.WriteLine(e.Message);
}
}
public static ObservableCollection<T> LoadList<T>(string folderName, string dataName) where T : class {
var retval = new ObservableCollection<T>();
if (!IsoStore.DirectoryExists(folderName) || !IsoStore.FileExists(folderName + "\\" + dataName + ".dat")) {
return retval;
}
string fileStreamName = string.Format("{0}\\{1}.dat", folderName, dataName);
var isf = IsoStore;
try {
var fileStream = IsoStore.OpenFile(fileStreamName, FileMode.OpenOrCreate);
if (fileStream.Length > 0) {
var dcs = new DataContractSerializer(typeof(ObservableCollection<T>));
retval = dcs.ReadObject(fileStream) as ObservableCollection<T>;
}
} catch {
retval = new ObservableCollection<T>();
}
return retval;
}
}
And I'm trying to use it this way
public partial class MainPage : PhoneApplicationPage{
public ObservableCollection<ListItem> ListItems = new ObservableCollection<ListItem>();
bool isListSaved;
private void Panorama_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e) {
if (strTag.Equals("list") ) {
isListSave = false;
ListItems = IsoStoreHelper.LoadList<ListItem>("settings", "ListItems");
} else if (!isListSave) {
IsoStoreHelper.SaveList<ListItem>("settings", "ListItems", ListItems);
}
}
}
I keep getting A first chance exception of type 'System.Security.SecurityException' occurred in System.Runtime.Serialization.ni.dll when I try read saved file at line ReadObject(fileStream) but the FileAccess looks fine.
Any conclusion will be appreciated.
SOLVED:
Like Dmytro Tsiniavskyi said I totaly forgot about [DataContract] and [DataMember] in ListItem. Whats more I found better solution for saving and loading data. I end up with this code for ListItem
[DataContract]
public class ListItem {
[DataMember]
public String Title { get; set; }
[DataMember]
public bool Checked { get; set; }
public ListItem(String title, bool isChecked=false) {
Title = title;
Checked = isChecked;
}
private ListItem() { }
}
And this code for save/load collection which was originally founded here and modified a litte bit for better useage.
public partial class IsolatedRW {
public static void SaveData<T>(string fileName, T dataToSave) {
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication()) {
try {
if (store.FileExists(fileName)) {
store.DeleteFile(fileName);
}
if (!store.DirectoryExists("Settings")) store.CreateDirectory("Settings");
IsolatedStorageFileStream stream;
using (stream = store.OpenFile("Settings/"+fileName+".xml", System.IO.FileMode.Create, System.IO.FileAccess.Write)) {
var serializer = new DataContractSerializer(typeof(T));
serializer.WriteObject(stream, dataToSave);
}
stream.Close();
} catch (System.Security.SecurityException e) {
//MessageBox.Show(e.Message);
return;
}
Debug.WriteLine(store.FileExists("Settings/" + fileName + ".xml"));
}
}
public static T ReadData<T>(string fileName) {
using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication()) {
Debug.WriteLine(store.FileExists("Settings/" + fileName + ".xml"));
if (store.FileExists("Settings/" + fileName + ".xml")) {
IsolatedStorageFileStream stream;
using (stream = store.OpenFile("Settings/"+fileName+".xml", FileMode.OpenOrCreate, FileAccess.Read)) {
try {
var serializer = new DataContractSerializer(typeof(T));
return (T)serializer.ReadObject(stream);
} catch (Exception) {
return default(T);
}
}
stream.Close();
}
return default(T);
}
}
}
Try to add [DataContract] attribute for your ListItem class.
[DataContract]
public class ListItem {
[DataMember]
public String Title { get; set; }
[DataMember]
public bool Checked { get; set; }
public ListItem(String title, bool isChecked=false) {
Title = title;
Checked = isChecked;
}
private ListItem() { }
}
I have a problem when I convert html page to a image using webbrowser it's taking Too much time with heavy html page.
It's works fine for small HTML Page but when html page is heavy then it stuck in
Application.DoEvent(); Function
WebBrowser m_WebBrowser = new WebBrowser();
m_WebBrowser.ScriptErrorsSuppressed = true;
m_WebBrowser.ScrollBarsEnabled = false;
m_WebBrowser.Navigate(m_Url);
m_WebBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted);
while (m_WebBrowser.ReadyState != WebBrowserReadyState.Complete)
**Application.DoEvents();**
m_WebBrowser.Dispose();
After Creating HTML page we pass the URL of the html page to this GetWebSiteThumbnail() function.
Code:
public class WebsiteThumbnailImageGenerator
{
public static Bitmap GetWebSiteThumbnail(string Url, int BrowserWidth, int BrowserHeight, int ThumbnailWidth, int ThumbnailHeight)
{
WebsiteThumbnailImage thumbnailGenerator = new WebsiteThumbnailImage(Url, BrowserWidth, BrowserHeight, ThumbnailWidth, ThumbnailHeight);
return thumbnailGenerator.GenerateWebSiteThumbnailImage();
}
private class WebsiteThumbnailImage
{
public WebsiteThumbnailImage(string Url, int BrowserWidth, int BrowserHeight, int ThumbnailWidth, int ThumbnailHeight)
{
this.m_Url = Url;
this.m_BrowserWidth = BrowserWidth;
this.m_BrowserHeight = BrowserHeight;
this.m_ThumbnailHeight = ThumbnailHeight;
this.m_ThumbnailWidth = ThumbnailWidth;
}
private string m_Url = null;
public string Url
{
get
{
return m_Url;
}
set
{
m_Url = value;
}
}
private Bitmap m_Bitmap = null;
public Bitmap ThumbnailImage
{
get
{
return m_Bitmap;
}
}
private int m_ThumbnailWidth;
public int ThumbnailWidth
{
get
{
return m_ThumbnailWidth;
}
set
{
m_ThumbnailWidth = value;
}
}
private int m_ThumbnailHeight;
public int ThumbnailHeight
{
get
{
return m_ThumbnailHeight;
}
set
{
m_ThumbnailHeight = value;
}
}
private int m_BrowserWidth;
public int BrowserWidth
{
get
{
return m_BrowserWidth;
}
set
{
m_BrowserWidth = value;
}
}
private int m_BrowserHeight;
public int BrowserHeight
{
get
{
return m_BrowserHeight;
}
set
{
m_BrowserHeight = value;
}
}
public Bitmap GenerateWebSiteThumbnailImage()
{
Thread m_thread = new Thread(new ThreadStart(_GenerateWebSiteThumbnailImage));
m_thread.SetApartmentState(ApartmentState.STA);
m_thread.Start();
m_thread.Join();
return m_Bitmap;
}
private void _GenerateWebSiteThumbnailImage()
{
WebBrowser m_WebBrowser = new WebBrowser();
m_WebBrowser.ScrollBarsEnabled = false;
m_WebBrowser.Navigate(m_Url);
m_WebBrowser.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(WebBrowser_DocumentCompleted);
while (m_WebBrowser.ReadyState != WebBrowserReadyState.Complete)
Application.DoEvents();
m_WebBrowser.Dispose();
}
private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser m_WebBrowser = (WebBrowser)sender;
m_WebBrowser.ClientSize = new Size(this.m_BrowserWidth, this.m_BrowserHeight);
m_WebBrowser.ScrollBarsEnabled = false;
m_Bitmap = new Bitmap(m_WebBrowser.Bounds.Width, m_WebBrowser.Bounds.Height);
m_WebBrowser.BringToFront();
m_WebBrowser.DrawToBitmap(m_Bitmap, m_WebBrowser.Bounds);
m_Bitmap = (Bitmap)m_Bitmap.GetThumbnailImage(m_ThumbnailWidth, m_ThumbnailHeight, null, IntPtr.Zero);
}
}
I changed your class a little bit and it now uses async/await instead of busy-waiting.
You can use it as
var th = new WebsiteThumbnailImage("http://www.google.com", 1024, 768, 256, 192);
this.BackgroundImage = await th.GenerateWebSiteThumbnailImage();
.
class WebsiteThumbnailImage
{
public WebsiteThumbnailImage(string Url, int BrowserWidth, int BrowserHeight, int ThumbnailWidth, int ThumbnailHeight)
{
this.Url = Url;
this.BrowserWidth = BrowserWidth;
this.BrowserHeight = BrowserHeight;
this.ThumbnailHeight = ThumbnailHeight;
this.ThumbnailWidth = ThumbnailWidth;
}
public string Url { set; get; }
public int ThumbnailWidth { set; get; }
public int ThumbnailHeight { set; get; }
public int BrowserWidth { set; get; }
public int BrowserHeight { set; get; }
private Bitmap m_Bitmap = null;
public Bitmap ThumbnailImage
{
get
{
return m_Bitmap;
}
}
public Task<Bitmap> GenerateWebSiteThumbnailImage()
{
var tcs = new TaskCompletionSource<Bitmap>();
WebBrowserDocumentCompletedEventHandler completed = null;
WebBrowser m_WebBrowser = new WebBrowser();
completed = (o, s) =>
{
_GenerateWebSiteThumbnailImageInternal(m_WebBrowser);
m_WebBrowser.DocumentCompleted -= completed;
m_WebBrowser.Dispose();
tcs.TrySetResult(m_Bitmap);
};
m_WebBrowser.ScrollBarsEnabled = false;
m_WebBrowser.ScriptErrorsSuppressed = true;
m_WebBrowser.DocumentCompleted += completed;
m_WebBrowser.Navigate(Url);
return tcs.Task;
}
private void _GenerateWebSiteThumbnailImageInternal(WebBrowser m_WebBrowser)
{
m_WebBrowser.ClientSize = new Size(this.BrowserWidth, this.BrowserHeight);
m_WebBrowser.ScrollBarsEnabled = false;
m_Bitmap = new Bitmap(m_WebBrowser.Bounds.Width, m_WebBrowser.Bounds.Height);
m_WebBrowser.BringToFront();
m_WebBrowser.DrawToBitmap(m_Bitmap, m_WebBrowser.Bounds);
m_Bitmap = (Bitmap)m_Bitmap.GetThumbnailImage(ThumbnailWidth, ThumbnailHeight, null, IntPtr.Zero);
}
}
Im trying to convert the response from the webclient to Json, but it's trying to create the JSON object before it is done downloaing it from the server.
Is there a "nice" way to for me to wait for WebOpenReadCompleted to be executed?
Have to mention that this is a WP7 app, so everything is Async
public class Client
{
public String _url;
private String _response;
private WebClient _web;
private JObject jsonsobject;
private Boolean blockingCall;
private Client(String url)
{
_web = new WebClient();
_url = url;
}
public JObject Login(String username, String password)
{
String uriUsername = HttpUtility.UrlEncode(username);
String uriPassword = HttpUtility.UrlEncode(password);
Connect(_url + "/data.php?req=Login&username=" + uriUsername + "&password=" + uriPassword + "");
jsonsobject = new JObject(_response);
return jsonsobject;
}
public JObject GetUserInfo()
{
Connect(_url + "/data.php?req=GetUserInfo");
jsonsobject = new JObject(_response);
return jsonsobject;
}
public JObject Logout()
{
Connect(_url + "/data.php?req=Logout");
jsonsobject = new JObject(_response);
return jsonsobject;
}
private void Connect(String url)
{
_web.Headers["Accept"] = "application/json";
_web.OpenReadCompleted += new OpenReadCompletedEventHandler(WebOpenReadCompleted);
_web.OpenReadAsync(new Uri(url));
}
private void WebOpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
if (e.Error != null || e.Cancelled)
{
MessageBox.Show("Error:" + e.Error.Message);
_response = "";
}
else
{
using (var reader = new StreamReader(e.Result))
{
_response = reader.ReadToEnd();
}
}
}
}
You can use an EventWaitHandle to nicely block until the async read is complete. I had a similar requirement for downloading files with WebClient. My solution was to subclass WebClient. Full source is below. Specifically, DownloadFileWithEvents blocks nicely until the async download completes.
It should be pretty straightforward to modify the class for your purpose.
public class MyWebClient : WebClient, IDisposable
{
public int Timeout { get; set; }
public int TimeUntilFirstByte { get; set; }
public int TimeBetweenProgressChanges { get; set; }
public long PreviousBytesReceived { get; private set; }
public long BytesNotNotified { get; private set; }
public string Error { get; private set; }
public bool HasError { get { return Error != null; } }
private bool firstByteReceived = false;
private bool success = true;
private bool cancelDueToError = false;
private EventWaitHandle asyncWait = new ManualResetEvent(false);
private Timer abortTimer = null;
const long ONE_MB = 1024 * 1024;
public delegate void PerMbHandler(long totalMb);
public event PerMbHandler NotifyMegabyteIncrement;
public MyWebClient(int timeout = 60000, int timeUntilFirstByte = 30000, int timeBetweenProgressChanges = 15000)
{
this.Timeout = timeout;
this.TimeUntilFirstByte = timeUntilFirstByte;
this.TimeBetweenProgressChanges = timeBetweenProgressChanges;
this.DownloadFileCompleted += new System.ComponentModel.AsyncCompletedEventHandler(MyWebClient_DownloadFileCompleted);
this.DownloadProgressChanged += new DownloadProgressChangedEventHandler(MyWebClient_DownloadProgressChanged);
abortTimer = new Timer(AbortDownload, null, TimeUntilFirstByte, System.Threading.Timeout.Infinite);
}
protected void OnNotifyMegabyteIncrement(long totalMb)
{
if (NotifyMegabyteIncrement != null) NotifyMegabyteIncrement(totalMb);
}
void AbortDownload(object state)
{
cancelDueToError = true;
this.CancelAsync();
success = false;
Error = firstByteReceived ? "Download aborted due to >" + TimeBetweenProgressChanges + "ms between progress change updates." : "No data was received in " + TimeUntilFirstByte + "ms";
asyncWait.Set();
}
void MyWebClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
if (cancelDueToError) return;
long additionalBytesReceived = e.BytesReceived - PreviousBytesReceived;
PreviousBytesReceived = e.BytesReceived;
BytesNotNotified += additionalBytesReceived;
if (BytesNotNotified > ONE_MB)
{
OnNotifyMegabyteIncrement(e.BytesReceived);
BytesNotNotified = 0;
}
firstByteReceived = true;
abortTimer.Change(TimeBetweenProgressChanges, System.Threading.Timeout.Infinite);
}
public bool DownloadFileWithEvents(string url, string outputPath)
{
asyncWait.Reset();
Uri uri = new Uri(url);
this.DownloadFileAsync(uri, outputPath);
asyncWait.WaitOne();
return success;
}
void MyWebClient_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
if (cancelDueToError) return;
asyncWait.Set();
}
protected override WebRequest GetWebRequest(Uri address)
{
var result = base.GetWebRequest(address);
result.Timeout = this.Timeout;
return result;
}
void IDisposable.Dispose()
{
if (asyncWait != null) asyncWait.Dispose();
if (abortTimer != null) abortTimer.Dispose();
base.Dispose();
}
}
I see you are using OpenReadAsync(). This is an asynchronous method, meaning that the calling thread is not suspended while the handler is executing.
This means your assignment operation setting jsonsobject happens while WebOpenReadCompleted() is still executing.
I'd say your best bet is to replace OpenReadAsync(new Uri(url)) with OpenRead(new Uri(url)) in your Connect(string url) method.
OpenRead() is a synchronous operation, so the calling method will wait until the WebOpenReadCompleted() method is complete before your assignment occurs in the Connect() method.