From 4da1fe41fac6e90980347f02bf4bb08b693e65ba Mon Sep 17 00:00:00 2001 From: Michel Feinstein Date: Thu, 27 Oct 2016 17:49:19 -0200 Subject: [PATCH 1/6] Made an MVVM friendly example. The example now complies better with MVVM. Added a Behavior for loading an HTML [WIP]. --- .../Behaviors/BindHtmlAttachedBehavior.cs | 47 +++++++++ .../Binding/BindableBase.cs | 24 +++++ .../Binding/RelayCommand.cs | 98 +++++++++++++++++++ .../CefSharp.MinimalExample.Wpf.csproj | 6 ++ CefSharp.MinimalExample.Wpf/MainViewModel.cs | 37 +++++++ CefSharp.MinimalExample.Wpf/MainWindow.xaml | 51 ++++++++-- .../MainWindow.xaml.cs | 1 + 7 files changed, 255 insertions(+), 9 deletions(-) create mode 100644 CefSharp.MinimalExample.Wpf/Binding/Behaviors/BindHtmlAttachedBehavior.cs create mode 100644 CefSharp.MinimalExample.Wpf/Binding/BindableBase.cs create mode 100644 CefSharp.MinimalExample.Wpf/Binding/RelayCommand.cs create mode 100644 CefSharp.MinimalExample.Wpf/MainViewModel.cs diff --git a/CefSharp.MinimalExample.Wpf/Binding/Behaviors/BindHtmlAttachedBehavior.cs b/CefSharp.MinimalExample.Wpf/Binding/Behaviors/BindHtmlAttachedBehavior.cs new file mode 100644 index 00000000..5334c45e --- /dev/null +++ b/CefSharp.MinimalExample.Wpf/Binding/Behaviors/BindHtmlAttachedBehavior.cs @@ -0,0 +1,47 @@ +using CefSharp.Wpf; +using System.Windows; +using System.Windows.Interactivity; + +namespace CefSharp.MinimalExample.Wpf.Binding.Behaviors +{ + public class LoadHtmlBehavior : Behavior + { + // Using a DependencyProperty as the backing store for Html. This enables animation, styling, binding, etc... + public static readonly DependencyProperty HtmlProperty = + DependencyProperty.Register( + "Html", + typeof(string), + typeof(LoadHtmlBehavior), + new PropertyMetadata(string.Empty, OnHtmlChanged)); + + // Using a DependencyProperty as the backing store for HtmlUrl. This enables animation, styling, binding, etc... + public static readonly DependencyProperty HtmlUrlProperty = + DependencyProperty.Register( + "HtmlUrl", + typeof(string), + typeof(LoadHtmlBehavior), + new PropertyMetadata(string.Empty)); + + public string Html + { + get { return (string)GetValue(HtmlProperty); } + set { SetValue(HtmlProperty, value); } + } + + public string HtmlUrl + { + get { return (string)GetValue(HtmlUrlProperty); } + set { SetValue(HtmlUrlProperty, value); } + } + + private static void OnHtmlChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if (e.NewValue == null || string.IsNullOrWhiteSpace((string)e.NewValue)) + { + return; + } + + (d as ChromiumWebBrowser)?.LoadHtml((string)e.NewValue, "http://test/page"); + } + } +} diff --git a/CefSharp.MinimalExample.Wpf/Binding/BindableBase.cs b/CefSharp.MinimalExample.Wpf/Binding/BindableBase.cs new file mode 100644 index 00000000..0e03dd33 --- /dev/null +++ b/CefSharp.MinimalExample.Wpf/Binding/BindableBase.cs @@ -0,0 +1,24 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace CefSharp.MinimalExample.Wpf.Binding +{ + public class BindableBase : INotifyPropertyChanged + { + protected virtual void SetProperty(ref T member, T val, + [CallerMemberName] string propertyName = null) + { + if (object.Equals(member, val)) { return; } + + member = val; + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + + protected virtual void OnPropertyChanged(string propertyName) + { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + + public event PropertyChangedEventHandler PropertyChanged = delegate { }; + } +} diff --git a/CefSharp.MinimalExample.Wpf/Binding/RelayCommand.cs b/CefSharp.MinimalExample.Wpf/Binding/RelayCommand.cs new file mode 100644 index 00000000..92a45bc1 --- /dev/null +++ b/CefSharp.MinimalExample.Wpf/Binding/RelayCommand.cs @@ -0,0 +1,98 @@ +using System; +using System.Windows.Input; + +namespace CefSharp.MinimalExample.Wpf.Binding +{ + public class RelayCommand : ICommand + { + Action _TargetExecuteMethod; + Func _TargetCanExecuteMethod; + + public RelayCommand(Action executeMethod) + { + _TargetExecuteMethod = executeMethod; + } + + public RelayCommand(Action executeMethod, Func canExecuteMethod) + { + _TargetExecuteMethod = executeMethod; + _TargetCanExecuteMethod = canExecuteMethod; + } + + public void RaiseCanExecuteChanged() + { + CanExecuteChanged(this, EventArgs.Empty); + } + #region ICommand Members + + bool ICommand.CanExecute(object parameter) + { + if (_TargetCanExecuteMethod != null) + { + return _TargetCanExecuteMethod(); + } + if (_TargetExecuteMethod != null) + { + return true; + } + return false; + } + + // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command + // Prism commands solve this in their implementation + public event EventHandler CanExecuteChanged = delegate { }; + + void ICommand.Execute(object parameter) + { + _TargetExecuteMethod?.Invoke(); + } + #endregion + } + + public class RelayCommand : ICommand + { + Action _TargetExecuteMethod; + Func _TargetCanExecuteMethod; + + public RelayCommand(Action executeMethod) + { + _TargetExecuteMethod = executeMethod; + } + + public RelayCommand(Action executeMethod, Func canExecuteMethod) + { + _TargetExecuteMethod = executeMethod; + _TargetCanExecuteMethod = canExecuteMethod; + } + + public void RaiseCanExecuteChanged() + { + CanExecuteChanged(this, EventArgs.Empty); + } + #region ICommand Members + + bool ICommand.CanExecute(object parameter) + { + if (_TargetCanExecuteMethod != null) + { + T tparm = (T)parameter; + return _TargetCanExecuteMethod(tparm); + } + if (_TargetExecuteMethod != null) + { + return true; + } + return false; + } + + // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command + // Prism commands solve this in their implementation + public event EventHandler CanExecuteChanged = delegate { }; + + void ICommand.Execute(object parameter) + { + _TargetExecuteMethod?.Invoke((T)parameter); + } + #endregion + } +} diff --git a/CefSharp.MinimalExample.Wpf/CefSharp.MinimalExample.Wpf.csproj b/CefSharp.MinimalExample.Wpf/CefSharp.MinimalExample.Wpf.csproj index 966eb5c8..b3c9781f 100644 --- a/CefSharp.MinimalExample.Wpf/CefSharp.MinimalExample.Wpf.csproj +++ b/CefSharp.MinimalExample.Wpf/CefSharp.MinimalExample.Wpf.csproj @@ -67,8 +67,10 @@ app.manifest + + @@ -86,6 +88,8 @@ MSBuild:Compile Designer + + MSBuild:Compile Designer @@ -94,7 +98,9 @@ App.xaml Code + + MainWindow.xaml Code diff --git a/CefSharp.MinimalExample.Wpf/MainViewModel.cs b/CefSharp.MinimalExample.Wpf/MainViewModel.cs new file mode 100644 index 00000000..ff3da854 --- /dev/null +++ b/CefSharp.MinimalExample.Wpf/MainViewModel.cs @@ -0,0 +1,37 @@ +using CefSharp.MinimalExample.Wpf.Binding; +using System.Windows.Input; + +namespace CefSharp.MinimalExample.Wpf +{ + public class MainViewModel : BindableBase + { + private string html; + + public MainViewModel() + { + ViewHtmlCommand = new RelayCommand(OnViewHtml); + Address = "www.google.com"; + } + + public string Html + { + get { return html; } + set { SetProperty(ref html, value); } + } + + private string address; + + public string Address + { + get { return address; } + set { SetProperty(ref address, value); } + } + + public ICommand ViewHtmlCommand { get; private set; } + + private void OnViewHtml() + { + Html = "
test
\r\n"; + } + } +} diff --git a/CefSharp.MinimalExample.Wpf/MainWindow.xaml b/CefSharp.MinimalExample.Wpf/MainWindow.xaml index 70ad9e34..afc25ff4 100644 --- a/CefSharp.MinimalExample.Wpf/MainWindow.xaml +++ b/CefSharp.MinimalExample.Wpf/MainWindow.xaml @@ -2,6 +2,8 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf" + xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" + xmlns:behaviors="clr-namespace:CefSharp.MinimalExample.Wpf.Binding.Behaviors" Title="{Binding Path=Title, ElementName=Browser, Converter={StaticResource TitleConverter}}" WindowState="Maximized"> @@ -11,16 +13,47 @@ + Address="{Binding Address}" > + + + + - - - - + + + + + + + + + + + + + + + + +