Remember Last Folder
Programs that remember where the user left off are much nicer to use. The .NET Framework provides standard infrastructure to persist application settings and it's well integrated with Visual Studio (see Figure 6). I only use it to remember the last source folder, but it can be extended to store any number of things like the size and position of the main window, the selected items in the current session and more.
There are several other issues you have to take into account when thinking about persistent application settings such as write access and shared settings between all users vs. per-user settings.
Once you figured it out, it is pretty easy to use application settings (especially in Visual Studio). You define your properties in the settings tab. Visual Studio takes care of adding two files: Settings.Designer.cs and Settings.cs. These files together define the sealed Settings class (via partial classes in each file) under the MP3DurationCalculator.Properties namespace. The Settings.Designer.cs file contains a static instance of the default settings and get/set properties for each setting:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.3603
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MP3DurationCalculator.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "9.0.0.0")]
internal sealed partial class Settings :
global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)
(global::System.Configuration.ApplicationSettingsBase.Synchronized(
new Settings())));
public static Settings Default {
get { return defaultInstance; }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
public string InitialFolder {
get { return ((string)(this["InitialFolder"])); }
set { this["InitialFolder"] = value; }
}
}
}
The Settings.cs file contains optional event handlers you can implement to respond to a change in settings and to intercept the saving process:
namespace MP3DurationCalculator.Properties
{
// This class allows you to handle specific events on the settings class:
// The SettingChanging event is raised before a setting's value is changed.
// The PropertyChanged event is raised after a setting's value is changed.
// The SettingsLoaded event is raised after the setting values are loaded.
// The SettingsSaving event is raised before the setting values are saved.
internal sealed partial class Settings
{
public Settings()
{
// To add event handlers for saving and changing settings, uncomment the
//lines below:
//
// this.SettingChanging += this.SettingChangingEventHandler;
//
// this.SettingsSaving += this.SettingsSavingEventHandler;
//
}
private void SettingChangingEventHandler(
object sender,
System.Configuration.SettingChangingEventArgs e)
{
// Add code to handle the SettingChangingEvent event here.
}
private void SettingsSavingEventHandler(
object sender, System.ComponentModel.CancelEventArgs e)
{
// Add code to handle the SettingsSaving event here.
}
}
}
MDC saves its settings in the OnExit method of the App class:
namespace MP3DurationCalculator
{
public partial class App : Application
{
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
MP3DurationCalculator.Properties.Settings.Default.Save();
}
}
}
When MDC is loaded the settings are loaded automatically and are available in the MainWindow constructor. If the initial folder doesn't exist than the user's MyMusic special folder is used as an initial folder:
public partial class MainWindow : Window
{
public MainWindow()
{
...
var initialFolder = Properties.Settings.Default.InitialFolder;
if (!Directory.Exists(initialFolder))
initialFolder =
Environment.GetFolderPath(Environment.SpecialFolder.MyMusic);
...
}
...
}
Give Me More...
Liat was pleased with all the changes and new features, but with the food comes the appetite. Once the initial excitement over MDC 2.0 subsided Liat wanted more features:
- Make CD from multiple source folders (will require merging of track_list.csv files)
- A full-fledged media control bar: play, pause, stop
- A seek bar that allows skipping and also displays the current position of the song
- Maybe a little database to manage prepared CDs and mark songs that were used already.
I guess this is a good sign. There are only two types of programs: the programs that users complain about and the programs they don't use.
Conclusion
The .NET Framework and WPF are a superb platform for developing rich client applications. It is designed well and supports both enterprise-grade applications as well as small fun utilities like MDC. I was able to extend MDC with a significant amount of user-requested functionality with minimal changes to the XAML and the code. The separation between UI description and data binding in XAML and event handling in code works very well. I'm looking forward to explore WPF further in the future.



