Master
Master

Reputation: 2163

Caching TextFields for application

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

Answers (1)

Mikko Viitala
Mikko Viitala

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;
    }
}


Below is screencap of the really amazing UI :) and related XML format.

imgur

<?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

Related Questions