patterncsharpMinor
Markdown Markup Editor: MK2
Viewed 0 times
mk2markdowneditormarkup
Problem
Following on from this question I have added some more functionality to Markdown Markup, and made it more WPF idiomatic.
It now supports saving data from any of the four boxes, and loading Markdown or CSS files.
Everything seems to work, so as always, any tips/pointers/critique is/are welcome.
So, first, the new
Nice and succinct.
The new
This is a bit larger than last time.
The
```
///
/// Represents a behavior to control WebBrowser binding to an HTML string.
///
///
/// Adopted from: http://stackoverflow.com/a/4204350/4564272
///
public class BrowserBehavior
{
public static readonly DependencyProperty HtmlProperty = DependencyProperty.RegisterAttached(
"Html",
typeof(string),
typeof(
It now supports saving data from any of the four boxes, and loading Markdown or CSS files.
Everything seems to work, so as always, any tips/pointers/critique is/are welcome.
So, first, the new
MainWindow.xaml.cs:///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
private MainWindowViewModel ViewModel => DataContext as MainWindowViewModel;
private void renderPreviewBrowser_Navigating(object sender, NavigatingCancelEventArgs e)
{
// This prevents links in the page from navigating, this also means we cannot call WebBrowser.Navigate for any browsers with this event.
if (e.Uri != null)
{
e.Cancel = true;
}
}
}Nice and succinct.
The new
MainWindow.xaml:
This is a bit larger than last time.
The
BrowserBehavior.cs:```
///
/// Represents a behavior to control WebBrowser binding to an HTML string.
///
///
/// Adopted from: http://stackoverflow.com/a/4204350/4564272
///
public class BrowserBehavior
{
public static readonly DependencyProperty HtmlProperty = DependencyProperty.RegisterAttached(
"Html",
typeof(string),
typeof(
Solution
OnPropertyChanged()This method to raise the
PropertyChanged event needs only to be called if the value is changed which isn't verified by the setters of your properties yet. To fix this issue and prevent unneeded work to be done a simple if condition is needed like sopublic string MarkdownContent
{
get { return _markdownContent; }
set
{
if (_markdownContent == value) { return; }
_markdownContent = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(MarkdownContent)));
UpdateHtml();
}
}The implementation of the
OnPropertyChanged() can be improved by just using the ? null-conditional operator which is clearly stated in the New Features in c# 6We expect that a very common use of this pattern will be for triggering of events:
PropertyChanged?.Invoke(this, args);This is an easy and thread-safe way to check for null before you trigger an event. The reason it’s thread-safe is that the feature evaluates the left-hand side only once, and keeps it in a temporary variable.
OpenMarkDown() and OpenCss()You have duplicated code here and an unused method parameter. By introducing a
string GetLoadFilename(string filter) (not sure about the method name) this can be prevented like soprivate string GetLoadFilename(string filter)
{
var dialog = new OpenFileDialog();
dialog.AddExtension = true;
dialog.Filter = filter;
var result = dialog.ShowDialog();
return result.Value ? dialog.FileName : string.Empty;
}and now for instance
OpenCss() would look like so if we also extract the actual reading of the file to a string ReadFile(string) methodpublic void OpenCss(object parameter)
{
var fileName = GetLoadFilename("CSS Files|*.css|All Files|*.*");
if (fileName.Length == 0) { return; }
CssContent = ReadFile(fileName)
}
private string ReadFile(string fileName)
{
using (var sr = new StreamReader(dialog.FileName))
{
return sr.ReadToEnd();
}
}Almost the same refactoring should be applied to the
SaveMarkdown(), SaveCss(), SaveGeneratedHtml() and SaveRenderedHtml() by introducing the methods string GetSaveFilename(string) and void SaveFile(string).Code Snippets
public string MarkdownContent
{
get { return _markdownContent; }
set
{
if (_markdownContent == value) { return; }
_markdownContent = value;
OnPropertyChanged(new PropertyChangedEventArgs(nameof(MarkdownContent)));
UpdateHtml();
}
}PropertyChanged?.Invoke(this, args);private string GetLoadFilename(string filter)
{
var dialog = new OpenFileDialog();
dialog.AddExtension = true;
dialog.Filter = filter;
var result = dialog.ShowDialog();
return result.Value ? dialog.FileName : string.Empty;
}public void OpenCss(object parameter)
{
var fileName = GetLoadFilename("CSS Files|*.css|All Files|*.*");
if (fileName.Length == 0) { return; }
CssContent = ReadFile(fileName)
}
private string ReadFile(string fileName)
{
using (var sr = new StreamReader(dialog.FileName))
{
return sr.ReadToEnd();
}
}Context
StackExchange Code Review Q#116015, answer score: 7
Revisions (0)
No revisions yet.