patterncsharpMinor
Markdown Markup Markleft Markright Editor
Viewed 0 times
markdowneditormarkrightmarkupmarkleft
Problem
I have a blog that I occasionally post to, but it's a PITA because of the fact that it has it's own WYSIWYG editor and doesn't support Markdown. So I have to switch the WYSIWYG editor to the HTML editor, and of course the HTML is garbled from the WYSIWYG editor.
So, I wrote a programme that I can feed Markdown into, and it will let me see what the HTML would be, and a preview of how it would look. It's all very simple.
The XAML:
The Code Behind:
```
using MarkdownSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Markdown_Markup
{
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
public static readonly DependencyProperty MarkdownHtmlProperty = DependencyProperty.Register("MarkdownHtml", typeof(string), typeof(MainWindow), new UIPropertyMetadata(string.Empty));
public string MarkdownHtml
{
get
{
return (string)GetValue(MarkdownHtmlProperty);
}
set
{
SetValue(MarkdownHtmlProperty, value);
}
}
public static readonly DependencyProperty RenderHtmlProperty = DependencyProperty.Register("RenderHtml", typeof(string), typeof(MainWindow), new UIPropertyMetadata(string.Empty));
public string RenderHtml
{
get
{
return (string)GetV
So, I wrote a programme that I can feed Markdown into, and it will let me see what the HTML would be, and a preview of how it would look. It's all very simple.
The XAML:
The Code Behind:
```
using MarkdownSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Markdown_Markup
{
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
public static readonly DependencyProperty MarkdownHtmlProperty = DependencyProperty.Register("MarkdownHtml", typeof(string), typeof(MainWindow), new UIPropertyMetadata(string.Empty));
public string MarkdownHtml
{
get
{
return (string)GetValue(MarkdownHtmlProperty);
}
set
{
SetValue(MarkdownHtmlProperty, value);
}
}
public static readonly DependencyProperty RenderHtmlProperty = DependencyProperty.Register("RenderHtml", typeof(string), typeof(MainWindow), new UIPropertyMetadata(string.Empty));
public string RenderHtml
{
get
{
return (string)GetV
Solution
You want to unleash the almighty power of WPF, and bind to a ViewModel; WPF and the Model-View-ViewModel design go completely hand-in-hand, especially if you like your code testable.
As it stands the only way to test the application logic is to actually run it and see what happens - that's good for a prototype app, but for an actual real-world app you'll want something a bit more robust.
Start with a class, and identify what your view needs - as always, input and output:
-
Input
-
Output
Easy as pie. Your ViewModel could start like this:
How is that used? I'll cheat a little and do this to illustrate:
Now your View knows about a ViewModel, and its
The MainWindow's
Now you can do this (removed fluff for clarity):
The
What does that entail? Whenever the markdown/css changes inside the textboxes, the ViewModel knows, because its setters are running - you have a handle to run your application logic, without writing a single line of code in the View's code-behind! No need to handle
Now, you can implement the application logic directly inside the ViewModel class, or better, you can constructor-inject the ViewModel with an object that's solely responsible for that.
As it stands the only way to test the application logic is to actually run it and see what happens - that's good for a prototype app, but for an actual real-world app you'll want something a bit more robust.
Start with a class, and identify what your view needs - as always, input and output:
-
Input
- Some Markdown content
- Some CSS content
-
Output
- The resulting HTML
Easy as pie. Your ViewModel could start like this:
public class MainWindowViewModel : INotifyPropertyChanged
{
private string _markdownContent;
public string MarkdownContent
{
get { return _markdownContent; }
set
{
_markdownContent = value;
OnPropertyChanged();
}
}
private string _cssContent;
public string CssContent
{
get { return _cssContent; }
set
{
_cssContent = value;
OnPropertyChanged();
}
}
private string _htmlContent;
public string HtmlContent
{
get { return _htmlContent; }
set
{
_htmlContent = value;
OnPropertyChanged();
}
}
// todo: INotifyPropertyChanged implementation
}How is that used? I'll cheat a little and do this to illustrate:
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
private MainWindowViewModel ViewModel
{
get { return DataContext As MainWindowViewModel; }
}Now your View knows about a ViewModel, and its
DataContext is set to an instance of it. You'll probably want a better way to do this though, but that's just to get the ball rolling.The MainWindow's
DataContext will now be inherited by everything in the XAML that doesn't override it - get rid of all that DataContext={foobar} markup, you don't need it anymore.Now you can do this (removed fluff for clarity):
The
WebBrowser is a little more fun (involves creating a behavior and an attached property - see the linked SO post), but at the end of the day boils down to this:What does that entail? Whenever the markdown/css changes inside the textboxes, the ViewModel knows, because its setters are running - you have a handle to run your application logic, without writing a single line of code in the View's code-behind! No need to handle
TextChanged, and no need to even name any of the controls!Now, you can implement the application logic directly inside the ViewModel class, or better, you can constructor-inject the ViewModel with an object that's solely responsible for that.
Code Snippets
public class MainWindowViewModel : INotifyPropertyChanged
{
private string _markdownContent;
public string MarkdownContent
{
get { return _markdownContent; }
set
{
_markdownContent = value;
OnPropertyChanged();
}
}
private string _cssContent;
public string CssContent
{
get { return _cssContent; }
set
{
_cssContent = value;
OnPropertyChanged();
}
}
private string _htmlContent;
public string HtmlContent
{
get { return _htmlContent; }
set
{
_htmlContent = value;
OnPropertyChanged();
}
}
// todo: INotifyPropertyChanged implementation
}public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
private MainWindowViewModel ViewModel
{
get { return DataContext As MainWindowViewModel; }
}<TextBox Content="{Binding MarkdownContent}"/>
<TextBox Content="{Binding CssContent}"/><WebBrowser local:BrowserBehavior.Html="{Binding HtmlContent}"/>Context
StackExchange Code Review Q#115919, answer score: 6
Revisions (0)
No revisions yet.