Reputation: 2163
I'm trying to load an application that has crashed with values that were entered before the save button was clicked. I've never dealt with caching and can't find many documentation on caching with WPF MVVM. If I may get some help.
PersonViewModel:
public string FirstName {get; set;}
public string LastName {get; set;}
PersonView.xaml.cs
<TextBlock Text ="{Binding FirstName}"/>
<TextBlock Text ="{Binding LastName}"/>
Example, I enter Billy Bob Into First and Last Name respectively and the application closes or is crashed before my save button is fired.
Upvotes: 0
Views: 169
Reputation: 8404
Of course you can "cache" user inputs if you will. One way to achieve this is by persisting data as user is typing.
If you have simple MainWindow.xaml
and MainWindow.xaml.cs
like so
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0">
<TextBox Text="{Binding User.FirstName,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
<TextBox Text="{Binding User.LastName,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged}" />
</StackPanel>
<Button Grid.Row="1" Content="Save" Command="{Binding SaveCommand}" />
</Grid>
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
Then using User
model you provided, given it implements INotifyPropertyChanged
, your MainViewModel
could be something like
public class MainViewModel : ViewModelBase
{
// "cache"
private readonly Cache<User> _cache;
private SaveCommand _saveCommand;
public MainViewModel()
{
// if exist, deserialize data
_cache = new Cache<User>();
User = _cache.Deserialize() ?? new User();
// listen properties for changes, serialize
User.PropertyChanged += (sender, args) => _cache.Serialize(User);
// provide cache file name to save command
SaveCommand = new SaveCommand(_cache.File);
CommandManager.RegisterClassCommandBinding(
typeof(MainViewModel), new CommandBinding(SaveCommand));
}
private User _user;
public User User
{
get { return _user; }
set { _user = value; OnPropertyChanged(); }
}
public ICommand SaveCommand { get; private set; }
}
In the above code you load the "cached" data into viewmodel's property if it exists. If not, just pass in a new instance. Then, while user types, all changes are immediately serialized (as XML).
When SaveCommand is executed, this cache is deleted. Otherwise it's available whenever user enters the main window (no matter if app was closed or crashed).
Cache<T>
below, along with simple SaveCommand
implementation.
public class Cache<T> where T : new()
{
private readonly XmlSerializer _serializer = new XmlSerializer(typeof(T));
private readonly string _file = string.Format("{0}.xml", typeof(T).Name);
public void Serialize(T obj)
{
using (var writer = XmlWriter.Create(_file))
_serializer.Serialize(writer, obj);
}
public T Deserialize()
{
if (!System.IO.File.Exists(File))
return default(T);
using (var reader = XmlReader.Create(_file))
return (T) _serializer.Deserialize(reader);
}
public string File { get { return _file; } }
}
public class SaveCommand : ICommand
{
public event EventHandler CanExecuteChanged;
private readonly string _file;
public SaveCommand(string file)
{
_file = file;
}
public void Execute(object parameter)
{
Debug.WriteLine("Save logic here, maybe...");
Debug.WriteLine(string.Format("...and remove cache file {0}", _file));
File.Delete(_file);
}
public bool CanExecute(object parameter)
{
return true;
}
}
<?xml version="1.0" encoding="utf-8"?>
<User xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<FirstName>My first...</FirstName>
<LastName>....and last name</LastName>
</User>
Upvotes: 1