Posted by: Zeeshan Amjad | January 26, 2014

FileDialogViewModel revisited


We saw the first very simple implementation of FileDialogViewModel here. There is still a room of improvement in this class. The first obvious improvement is to get the name of open file. In previous version, we don’t have any indication on the screen that which file is currently open. Now let’s add this functionality.

The first step is to add the property in our FileService helper class because that class actually uses the OpenFileDialog and SaveFileDialog classes. Here is an updated version of our class.

Code Snippet
public sealed class FileService
{
    public string FileName
    {
        get;
        set;
    }

    public Stream OpenFile(string defaultExtension, string filter)
    {
        OpenFileDialog fd = new OpenFileDialog();
        fd.DefaultExt = defaultExtension;
        fd.Filter = filter;
        fd.Multiselect = false;

        bool? result = fd.ShowDialog();
        this.FileName = fd.FileName;

        return result.Value ? fd.OpenFile() : null;
    }

    public Stream SaveFile(string defaultExtension, string filter)
    {
        SaveFileDialog fd = new SaveFileDialog();
        fd.DefaultExt = defaultExtension;
        fd.Filter = filter;               

        bool? result = fd.ShowDialog();
        this.FileName = fd.FileName;

        return result.Value ? fd.OpenFile() : null;
    }        
}

 

Now we have to add this property in our FileDialogViewModel too. Here is our updated version of FileDialogViewModel class.

Code Snippet
public class FileDialogViewModel : ViewModelBase
{
    private string extension;
    private string filter;
    private string fileName;

    public FileDialogViewModel()
    {
        this.SaveCommand = new RelayCommand(this.SaveFile);
        this.OpenCommand = new RelayCommand(this.OpenFile);            
    }

    #region Properties

    public Stream Stream
    {
        get;
        set;
    }

    public string Extension
    {
        get
        {
            return this.extension;
        }

        set
        {
            this.extension = value;
            this.RaisePropertyChanged("Extension");
        }
    }

    public string Filter
    {
        get
        {
            return this.filter;
        }

        set
        {
            this.filter = value;
            this.RaisePropertyChanged("Filter");
        }
    }

    public string FileName
    {
        get
        {
            return this.fileName;
        }

        set
        {
            this.fileName = value;
            this.RaisePropertyChanged("FileName");
        }
    }

    public ICommand OpenCommand
    {
        get;
        set;
    }

    public ICommand SaveCommand
    {
        get;
        set;
    }

    #endregion

    private void OpenFile()
    {
        FileService fileServices = new FileService();
        this.Stream = fileServices.OpenFile(this.Extension, this.Filter);
        this.FileName = fileServices.FileName;
    }

    private void SaveFile()
    {
        FileService fileServices = new FileService();
        this.Stream = fileServices.SaveFile(this.Extension, this.Filter);
        this.FileName = fileServices.FileName;
    }
}

 

Now we can use this new property in another view model or even in XAML. In our previous example, we are creating an instance of FileDialogViewModel inside the MainViewModel. Let’s use the same approach and use this new property.

Code Snippet
public class MainViewmodel : ViewModelBase
{
    private string text;
    private string fileName;

    public MainViewmodel()
    {
        this.SaveCommand = new RelayCommand(this.SaveFile);
        this.OpenCommand = new RelayCommand(this.OpenFile);            
    }

    #region Properties

    public string Text
    {
        get
        {
            return this.text;
        }

        set
        {
            this.text = value;
            this.RaisePropertyChanged("Text");
        }
    }

    public string FileName
    {
        get
        {
            return string.IsNullOrEmpty(this.fileName) ? "No file selected" : this.fileName;
        }

        set
        {
            this.fileName = value;
            this.RaisePropertyChanged("FileName");
        }
    }

    public ICommand OpenCommand
    {
        get;
        set;
    }

    public ICommand SaveCommand
    {
        get;
        set;
    }

    #endregion

    private void OpenFile()
    {
        FileDialogViewModel fdvm = new FileDialogViewModel();
        fdvm.Extension = "*.txt";
        fdvm.Filter = "Text documents (.txt)|*.txt";

        fdvm.OpenCommand.Execute(null);

        if (fdvm.Stream == null)
            return;

        this.FileName = fdvm.FileName;

        using (StreamReader sr = new StreamReader(fdvm.Stream, Encoding.ASCII))
        {
            this.Text = sr.ReadToEnd();
        }
    }

    private void SaveFile()
    {
        FileDialogViewModel fdvm = new FileDialogViewModel();
        fdvm.Extension = "*.txt";
        fdvm.Filter = "Text documents (.txt)|*.txt";

        fdvm.SaveCommand.Execute(null);

        if (fdvm.Stream == null)
            return;

        this.FileName = fdvm.FileName;

        using (StreamWriter sw = new StreamWriter(fdvm.Stream, Encoding.ASCII))
        {
            sw.Write(this.Text.ToString(CultureInfo.InvariantCulture));    
        }           
    }
}

 

In XAML we just bind the new property to the tile of the main window to display the currently open file name in the title bar. Here is our XAML code of updated simple text editor.

Code Snippet
<Window x:Class="WpfFileDialog.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml&quot;
        Title="{Binding FileName}" Height="350" Width="525">
    <Grid DataContext="{Binding}">
        <Grid.RowDefinitions>
            <RowDefinition Height="4*"/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <TextBox Grid.Column="0" Grid.Row="0" Grid.ColumnSpan="2" Margin="10"
                 TextWrapping="Wrap" AcceptsReturn="True"
                 HorizontalScrollBarVisibility="Auto"
                 VerticalScrollBarVisibility="Auto"
                 Text="{Binding Text}"/>
        <Button Grid.Column="0" Grid.Row="2" Margin="10"
                Command="{Binding OpenCommand}">
            Open
        </Button>
        <Button Grid.Column="1" Grid.Row="2" Margin="10"
                Command="{Binding SaveCommand}">
            Save
        </Button>
    </Grid>
</Window>

 

This is a screen shot of the program. Notice the file name is displayed at the title bar.

FileDialogViewModel2

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: