简体   繁体   中英

Web Browser Control in WPF

My goal is similar to this question
But still I didn't get answer to my problem

So, I need make an app with WYSIWYG HTML editing support for designing and generating report template. And like question above, I used WebBrowser control in WPF. The biggest problem is WPF WebBrowser always set null to HTML body after designMode set to on. So I host WinForm WebBrowser into my app. And to set or to get HTML document to be processed from WebBrowser is incredibly hard.

Q:

  1. Is there any way to make this (HTML Editor using WebBrowser Control) happen using WPF without change to WinForm ?
  2. Or, if not. Is there any workaround, article, code or any whatever to make WYSIWYG HTML Editor with visual editor ?

UPDATE:
I have these 2 attached property for MVVM purposes. So I can get/set HTML with HTMLSource and set Design Mode when app launched.

IsDesignMode

public static readonly DependencyProperty IsDesignModeProperty =
    DependencyProperty.RegisterAttached("IsDesignMode", typeof (Boolean), typeof (WebBrowserHelper),
                                        new UIPropertyMetadata(false, IsDesignModePropertyChanged));

public static Boolean GetIsDesignMode(DependencyObject obj)
{
    return (Boolean)obj.GetValue(IsDesignModeProperty);
}

public static void SetIsDesignMode(DependencyObject obj, Boolean value)
{
    obj.SetValue(IsDesignModeProperty, value);
}

public static void IsDesignModePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
{
    WebBrowser browser = obj as WebBrowser;
    if (browser != null)
    {
        Boolean designMode = (Boolean) args.NewValue;
        if(designMode)
        {
            browser.LoadCompleted += (s, e) =>
            {
                var htmlDoc = (s as WebBrowser).Document as IHTMLDocument2;
                htmlDoc.body.setAttribute("contenteditable", "true");
                htmlDoc.designMode = "On";
            };
        }
        else
        {
            browser.LoadCompleted += (s, e) =>
            {
                var htmlDoc = (s as WebBrowser).Document as IHTMLDocument2;
                htmlDoc.body.setAttribute("contenteditable", "false");
                htmlDoc.designMode = "Off";
            };
        }
    }
}

HTMLSource

public static readonly DependencyProperty HTMLSourceProperty =
    DependencyProperty.RegisterAttached("HTMLSource", typeof (String), typeof (WebBrowserHelper),
                                        new UIPropertyMetadata(null, HTMLSourcePropertyChanged));

public static String GetHTMLSource(DependencyObject obj)
{
    return (String)obj.GetValue(HTMLSourceProperty);
}

public static void SetHTMLSource(DependencyObject obj, String value)
{
    obj.SetValue(HTMLSourceProperty, value);
}

public static void HTMLSourcePropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs args)
{
    WebBrowser browser = o as WebBrowser;
    if (browser != null)
    {
        browser.NavigateToString(args.NewValue as String);
    }
}

VIEW

<UserControl x:Class="Delay.View.LayoutView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:browser="clr-namespace:Delay.Helper"
             xmlns:cal="http://www.caliburnproject.org"
             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
    <UserControl.Resources>
        <Style x:Key="ButtonStyle" TargetType="Button">
            <Setter Property="Width" Value="100" />
            <Setter Property="Height" Value="40" />
            <Setter Property="Margin" Value="2.5,0" />
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <StackPanel>
                            <ContentPresenter Content="{TemplateBinding Content}"
                                              TextBlock.FontSize="15" />
                        </StackPanel>
                    </DataTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>
    <Grid Background="Lavender">
        <DockPanel>
            <TextBlock HorizontalAlignment="Center" Text="Layout Designer"
                       DockPanel.Dock="Top" FontSize="20" />
            <WebBrowser Name="webBrowser" HorizontalAlignment="Stretch" DockPanel.Dock="Top" Margin="8" Height="435"
                        browser:WebBrowserHelper.HTMLSource="{Binding HtmlPage}" browser:WebBrowserHelper.IsDesignMode="True" />
            <StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom" HorizontalAlignment="Center">
                <StackPanel Orientation="Vertical" Margin="5,0">
                    <ComboBox ItemsSource="{Binding LayoutTags}" SelectedItem="{Binding SelectedTag}"
                              HorizontalAlignment="Stretch" Margin="0,5" MinWidth="100">
                        <ComboBox.ItemTemplate>
                            <DataTemplate>
                                <TextBlock FontSize="12" Text="{Binding TagName}" />
                            </DataTemplate>
                        </ComboBox.ItemTemplate>
                    </ComboBox>
                    <ListBox ItemsSource="{Binding LayoutValueTypes}" SelectedItem="{Binding SelectedType}"
                             Width="{Binding ElementName=cmbTag, Path=ActualWidth}" Height="70">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <TextBlock FontSize="12" Text="{Binding TypeName}" />
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </StackPanel>
                <StackPanel Orientation="Vertical">
                    <StackPanel Orientation="Horizontal">
                        <CheckBox Name="IsDesignMode" Content="Design Mode" TextBlock.FontSize="12">
                            <i:Interaction.Triggers>
                                <i:EventTrigger EventName="Checked">
                                    <cal:ActionMessage MethodName="DesignModeOnOff">
                                        <cal:Parameter Value="{Binding ElementName=webBrowser}" />
                                        <cal:Parameter Value="{Binding IsDesignMode}" />
                                    </cal:ActionMessage>
                                </i:EventTrigger>
                            </i:Interaction.Triggers>
                        </CheckBox>
                    </StackPanel>
                    <Button Name="PutComponent" Style="{StaticResource ButtonStyle}"
                         Content="Put" />
                    <Button Name="SaveLayout" Style="{StaticResource ButtonStyle}"
                        Content="Save" />
                </StackPanel>
            </StackPanel>
        </DockPanel>
    </Grid>
</UserControl>

Did you try some open source alternatives instead of the WInForms one?

I think this one has good interaction, and can handle javascript callbacks into wpf too.

http://wpfchromium.codeplex.com/

I wrote a very simple WPF app that used an embedded resource as HTML and included the following code:

  Stream s = GetType().Assembly.GetManifestResourceStream("WpfApplication5.HTMLPage1.htm");
  webBrowser1.NavigateToStream(s);
  IHTMLDocument2 doc = webBrowser1.Document as IHTMLDocument2;
  doc.designMode = "On";

The code worked as expected an I could edit the content of the page - it was not nulled out once I set it to designMode as you suggested. Perhaps start with the code above and check you can get that to work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM