从ViewModel绑定的ObservableCollection不更新视图
本文关键字:更新 新视图 ObservableCollection ViewModel 绑定 | 更新日期: 2023-09-27 18:27:30
我允许用户通过视图中的ContextMenu菜单项删除项目,我希望在视图中自动看到效果。截至目前,视图中的项目一直保留到应用程序重新启动,在这种情况下,它将不再可见。对于认为该项目已从应用程序中完全删除的用户来说,这是非常令人困惑的。我的问题是,我做错了什么才能解决这个问题?
App.xaml.cs
//PictureRepository is a class that gathers pictures from IsolatedStorage
public static PictureRepository PictureList
{
get
{
return PictureRepository.Instance;
}
}
图片库.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);
}
}
主页.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;
}
}
}
正如您所看到的,我正试图从View and IsolatedStorage中删除该项。到目前为止,从IsolatedStorage中删除操作正在进行,但我似乎无法自动更新视图?我必须等到应用程序重新启动并且ListBox在OnNavigatedTo
事件中重新填充后才能看到任何更改。
问题是您将IOrderedEnumerable分配给Recent.ItemSource,而不是ObservableCollection。
在LoadAllPicturesFromIsolatedStorage()中,创建一个临时列表,在其中添加文件中加载的数据,然后创建ObservableCollection。
图片库.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));
}
在MainPage.cs上,将您的OnNavigatedTo方法更改为:
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;
}