|
namespace HTMLTitleParser.ViewModel
{
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Progress;
public partial class AppVM : BaseVM
{
#region fields
// Default directory to scan for HTML files
private string mPath = HTMLTitleParser.View.Main.DirMyDocuments;
private ProgressVM mProcessing = null;
private Dictionary<string, string> mMapFile2Title;
#endregion fields
#region Constructor
public AppVM()
{
this.Processing = new ProgressVM() { StatusMessage = ProgressVM.StrReady };
this.mMapFile2Title = new Dictionary<string, string>();
}
#endregion Constructor
#region Enums
/// <summary>
/// Types of supported long running processes
/// </summary>
internal enum TypeOfProcess
{
ProcessHTML = 0,
MultiProcessHTML = 1
}
#endregion Enums
#region Properties
/// <summary>
/// Path to directory containing HTML to be scanned
/// </summary>
public string Path
{
get
{
return this.mPath;
}
set
{
if (this.mPath != (value == null ? string.Empty : value))
{
this.mPath = (value == null ? string.Empty : value);
this.OnPropertyChanged(Bind.PropName(() => this.Path));
}
}
}
/// <summary>
/// Property to display HTML file paths and their HTML TITLE TAG content
/// </summary>
public Dictionary<string, string> MapFile2Title
{
get
{
return (this.mMapFile2Title == null ? new Dictionary<string, string>() : this.mMapFile2Title);
}
set
{
if (this.mMapFile2Title != value)
{
this.mMapFile2Title = (value == null ? new Dictionary<string, string>() : value);
this.OnPropertyChanged(Bind.PropName(() => this.MapFile2Title));
}
}
}
/// <summary>
/// Processing ViewModel exposing properties for progressbar
/// visibility and start/stop GUI enablements.
/// </summary>
public ProgressVM Processing
{
get
{
return this.mProcessing;
}
private set
{
this.mProcessing = value;
this.OnPropertyChanged(Bind.PropName(() => this.Processing));
}
}
#endregion Properties
#region Methods
/// <summary>
/// Determine whether a command can be executed based on the fact
/// if there is a background process in progress or not.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void CanExecute_IfNoProcessRuns(object sender, CanExecuteRoutedEventArgs e)
{
e.Handled = true;
if (e != null && this.Processing != null)
{
string sProcessName; // Allow only if there is no other process running
e.CanExecute = !this.ProcessIsRunning(out sProcessName);
return;
}
e.CanExecute = false;
}
/// <summary>
/// Main entry point of simple HTML processing in the
/// Applictaion ViewModel. This method does all the housekeeping
/// to bind GUI controls to their respective properties. Start the
/// backgound processing and registers another result method
/// <see cref="AppVM.ProcessHTML_Results"/> to be executed
/// when the background processing is finished (with or without errors).
/// </summary>
/// <param name="e"></param>
/// <param name="progressBar"></param>
/// <param name="statusTextBox"></param>
/// <param name="lstResults"></param>
/// <param name="btnStop"></param>
/// <returns></returns>
public bool ProcessHTMLDirectory(ExecutedRoutedEventArgs e,
ProgressBar progressBar,
TextBox statusTextBox,
ListView statusListView,
ListView lstResults,
Button btnStop)
{
e.Handled = true;
string dirPath = (string)e.Parameter;
if (this.Processing != null)
{ // Emergency stop: Don't run twice...
if (this.Processing.CanCancelRunProcess == true)
return false;
}
try
{
// Check if process is currently running or not
string sProcessName;
if (this.ProcessIsRunning(out sProcessName) == true)
{
MessageBox.Show("A " + sProcessName + " is currently being executed. Only one process can be executed at a time.", "Process is being executed",
MessageBoxButton.OK, MessageBoxImage.Information);
return false;
}
this.BindStatusBarItems(TypeOfProcess.ProcessHTML,
progressBar, statusTextBox, statusListView,
lstResults, btnStop, this.ProcessHTML_Results);
this.Processing.SetProgressVisibility(true);
// Force refresh of CanExecute Command framework functions ...
CommandManager.InvalidateRequerySuggested();
Dictionary<string, object> callParams = new Dictionary<string, object>();
callParams.Add(ViewModel.ProcessHTMLVM.KeyDirPath, dirPath);
// Set parameters (if any) and method to run and run it asynchronously
this.Processing.RunProcess(true, callParams, ((ProcessHTMLVM)this.Processing).ProcessHTMLDirectory);
}
catch (Exception exc)
{
MessageBox.Show(exc.ToString());
}
return true;
}
/// <summary>
/// Cancel processing of the currently running process
/// </summary>
/// <param name="e"></param>
public void CancelProcessing(ExecutedRoutedEventArgs e)
{
e.Handled = true;
if (this.mProcessing != null)
this.mProcessing.Cancel();
}
/// <summary>
/// Determine whether a process is currently running or not and return its name (if any)
/// </summary>
/// <returns></returns>
internal bool ProcessIsRunning(out string processName)
{
processName = string.Empty;
if (this.Processing != null)
{
if (this.Processing.CanCancelRunProcess == true)
{
processName = this.Processing.ProcessName;
return true;
}
}
return false;
}
/// <summary>
/// This function is called when the <seealso cref="ProcessHTMLDirectory.ProcessHTMLDirectory"/>
/// completes. The <paramref name="e"/> parameter is used to display the result in the GUI.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ProcessHTML_Results(object sender, ProcessHTMLVM.ProgressResult e)
{
// Force refresh of CanExecute Command framework functions ...
CommandManager.InvalidateRequerySuggested();
if (e.Cancel == true || e.Error == true)
{
if (e.Cancel == true)
this.Processing.StatusMessage = string.Format("Cancelled by user with result code {0}", e.ResultCode);
else
{
if (e.InnerException != null)
this.Processing.StatusMessage = string.Format("{0}, result code:{1}", e.InnerException.Message, e.ResultCode);
else
this.Processing.StatusMessage = string.Format("Process finished with errors and result code {0}", e.ResultCode);
}
return;
}
// Set processing result in application viewmodel and make it visible in GUI
object o;
if (e.ResultObjects.TryGetValue(ProcessHTMLVM.KeyMapFileToTitle, out o) == true)
this.MapFile2Title = o as Dictionary<string, string>;
// Reset status message to indicate that the system is wating for input
this.Processing.StatusMessage = ProgressVM.StrReady;
}
/// <summary>
/// Reset GUI bindings of progress elements and construct a new processing class
/// (eg.: for Backup/Restore operation)
/// </summary>
/// <param name="progressBar"></param>
/// <param name="statusTextBox"></param>
/// <param name="lstResults"></param>
/// <param name="btnStop"></param>
/// <param name="btnExec"></param>
private void BindStatusBarItems(TypeOfProcess typeOfProcess,
ProgressBar progressBar,
TextBox statusTextBox,
ListView statusListView,
ListView lstResults,
Button btnStop,
EventHandler<ProgressVM.ProgressResult> processCompleted = null)
{
ProgressVM retProcess = null;
switch (typeOfProcess)
{
case TypeOfProcess.ProcessHTML:
retProcess = new ProcessHTMLVM();
break;
default:
throw new NotImplementedException(
string.Format("The process type: {0} is not supported.", typeOfProcess));
}
// Get an initially collapsed progress bar plus binding
ProgressVM tExec = ProgressVM.BindProgressStatusItems(
retProcess, progressBar, statusTextBox, statusListView, lstResults, btnStop);
tExec.CanRunProcess = false;
tExec.CanCancelRunProcess = true;
if (processCompleted != null)
tExec.resultEvent += processCompleted;
this.Processing = tExec;
}
#endregion Methods
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
The Windows Presentation Foundation (WPF) and C# are among my favorites and so I developed
Edi
and a few other projects on
GitHub. I am normally an algorithms and structure type but WPF has such interesting UI sides that I cannot help myself but get into it.
https://de.linkedin.com/in/dirkbahle