C # WebBrowser контроль не применяет CSS - PullRequest
8 голосов
/ 01 апреля 2010

У меня есть проект, над которым я работаю в VS2005. Я добавил элемент управления WebBrowser. Я добавляю базовую пустую страницу в элемент управления

private const string _basicHtmlForm = "<html> "
                                      + "<head> "
                                      + "<meta http-equiv='Content-Type' content='text/html; charset=utf-8'/> "
                                      + "<title>Test document</title> "
                                      + "<script type='text/javascript'> "
                                      + "function ShowAlert(message) { "
                                      + "   alert(message); "
                                      + "} "
                                      + "</script> "
                                      + "</head> "
                                      + "<body><div id='mainDiv'> "
                                      + "</div></body> "
                                      + "</html> ";

private string _defaultFont = "font-family: Arial; font-size:10pt;";

private void LoadWebForm()
{
    try 
    {
        _webBrowser.DocumentText = _basicHtmlForm;
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}  

, а затем добавьте различные элементы через dom (используя _webBrowser.Document.CreateElement). Я также загружаю файл CSS:

private void AddStyles()
{
    try
    {
        mshtml.HTMLDocument currentDocument = (mshtml.HTMLDocument) _webBrowser.Document.DomDocument;
        mshtml.IHTMLStyleSheet styleSheet = currentDocument.createStyleSheet("", 0);

        TextReader reader = new StreamReader(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath),"basic.css"));
        string style = reader.ReadToEnd();
        styleSheet.cssText = style;
    }
    catch(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Вот содержимое страницы css:

body {
    background-color: #DDDDDD;
}

.categoryDiv {
    background-color: #999999;
}

.categoryTable {
    width:599px; background-color:#BBBBBB;
}

#mainDiv {
    overflow:auto; width:600px;
}

Страница стиля успешно загружается, но единственные элементы на странице, на которые влияют, это те элементы, которые изначально находятся на странице (body и mainDiv). Я также попытался включить css в элемент в разделе заголовка, но он по-прежнему влияет только на элементы, которые присутствуют при создании страницы.

Так что мой вопрос: кто-нибудь имеет представление о том, почему CSS не применяется к элементам, которые создаются после загрузки страницы? Я также пытался не применять css, пока все мои элементы не были добавлены, но результаты не изменились.

Ответы [ 7 ]

6 голосов
/ 22 июня 2010

Я внес небольшое изменение в ваш метод AddStyles (), и он работает для меня. Откуда ты звонишь? Я вызвал его из "_webBrowser_DocumentCompleted".

Я должен указать, что я вызываю AddStyles после того, как я изменяю DOM.

private void AddStyles()
{
    try
    {
        if (_webBrowser.Document != null)
        {
            IHTMLDocument2 currentDocument = (IHTMLDocument2)_webBrowser.Document.DomDocument;

            int length = currentDocument.styleSheets.length;
            IHTMLStyleSheet styleSheet = currentDocument.createStyleSheet(@"", length + 1);
            //length = currentDocument.styleSheets.length;
            //styleSheet.addRule("body", "background-color:blue");
            TextReader reader = new StreamReader(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "basic.css"));
            string style = reader.ReadToEnd();
            styleSheet.cssText = style;

        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Вот мой обработчик DocumentCompleted (я добавил несколько стилей в basic.css для тестирования):

private void _webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
  HtmlElement element = _webBrowser.Document.CreateElement("p");
  element.InnerText = "Hello World1";
  _webBrowser.Document.Body.AppendChild(element);

  HtmlElement divTag = _webBrowser.Document.CreateElement("div");
  divTag.SetAttribute("class", "categoryDiv");
  divTag.InnerHtml = "<p>Hello World2</p>";
  _webBrowser.Document.Body.AppendChild(divTag);


  HtmlElement divTag2 = _webBrowser.Document.CreateElement("div");
  divTag2.SetAttribute("id", "mainDiv2");
  divTag2.InnerHtml = "<p>Hello World3</p>";
  _webBrowser.Document.Body.AppendChild(divTag2);

  AddStyles();
}

Это то, что я получаю (изменил стиль, чтобы сделать его таким уродливым, каким его может надеяться один человек: D):

альтернативный текст http://www.freeimagehosting.net/uploads/2e372f7276.png

1 голос
/ 21 июня 2010

Одним из решений является проверка HTML до установки DocumentText и внедрение CSS на стороне клиента. Я не устанавливаю свойство элемента управления URL, а получаю HTML через WebCLient и затем устанавливаю DocumentText. возможно, установив DocumentText (или в вашем случае Document) после того, как вы манипулируете DOM, можно заставить его правильно перерисовать

private const string CSS_960 = @"960.css";
private const string SCRIPT_FMT = @"<style TYPE=""text/css"">{0}</style>";
private const string HEADER_END = @"</head>";


 public void SetDocumentText(string value)
{
    this.Url = null;  // can't have both URL and DocText
    this.Navigate("About:blank");
    string css = null;
    string html = value;

    // check for known CSS file links and inject the resourced versions
    if(html.Contains(CSS_960))
    {
      css = GetEmbeddedResourceString(CSS_960);
      html = html.Insert(html.IndexOf(HEADER_END), string.Format(SCRIPT_FMT,css));
    }

    if (Document != null) { 
      Document.Write(string.Empty);
    }
    DocumentText = html;
}
0 голосов
/ 16 июня 2010

Похоже, что phq испытал это. Я думаю, что я подойду, добавив ссылку на jquery в ваш HTML-документ (с самого начала).

Затем внутри страницы создайте функцию javascript, которая принимает идентификатор элемента и имя применяемого класса. Внутри функции используйте jquery для динамического применения рассматриваемого класса или для непосредственного изменения CSS. Например, используйте .addClass или .css функции jquery для изменения элемента.

Оттуда, в вашем коде C #, после добавления элемента динамически вызывайте этот javascript, как описано здесь Риком Стрэлом: http://www.west -wind.com / Weblog / posts / 493536.aspx

0 голосов
/ 09 июня 2010

Возможно, что объекты на странице EXIST во время загрузки страницы, поэтому можно применять каждый стиль. просто то, что вы добавляете узел в дерево DOM, не означает, что все его атрибуты могут обрабатываться и отображаться внутри браузера. описанные выше методы, кажется, используют подход перезагрузки страницы (DOM), что предполагает, что это может иметь место. Короче говоря, обновите страницу после добавления элемента

0 голосов
/ 08 июня 2010

Я использую аналогичное управление вместо WebBrowser, загружаю HTML-страницу с правилами стиля «по умолчанию» и меняю правила в программе.

(DrawBack - сопровождение, когда мне нужно добавить правило, мне также нужно изменить его в коде)

' ----------------------------------------------------------------------
Public Sub mcFontOrColorsChanged(ByVal isRefresh As Boolean)  
  ' ----------------------------------------------------------------------
  ' Notify whichever is concerned:
  Dim doc As mshtml.HTMLDocument = Me.Document
  If (doc.styleSheets Is Nothing) Then Return
  If (doc.styleSheets.length = 0) Then Return
  Dim docStyleSheet As mshtml.IHTMLStyleSheet = CType(doc.styleSheets.item(0), mshtml.IHTMLStyleSheet)
  Dim docStyleRules As mshtml.HTMLStyleSheetRulesCollection = CType(docStyleSheet.rules, mshtml.HTMLStyleSheetRulesCollection)

  ' Note: the following is needed seperately from 'Case "BODY"
  Dim docBody As mshtml.HTMLBodyClass = CType(doc.body, mshtml.HTMLBodyClass)
  If Not (docBody Is Nothing) Then
    docBody.style.backgroundColor = colStrTextBg 
  End If

  Dim i As Integer
  Dim maxI As Integer = docStyleRules.length - 1
  For i = 0 To maxI
    Select Case (docStyleRules.item(i).selectorText)
      Case "BODY"
        docStyleRules.item(i).style.fontFamily = fName ' "Times New Roman" | "Verdana" | "courier new" | "comic sans ms" | "Arial"
      Case "P.myStyle1"
        docStyleRules.item(i).style.fontSize = fontSize.ToString & "pt"
      Case "TD.myStyle2" ' do nothing  
      Case ".myStyle3"
        docStyleRules.item(i).style.fontSize = fontSizePath.ToString & "pt"
        docStyleRules.item(i).style.color = colStrTextFg
        docStyleRules.item(i).style.backgroundColor = colStrTextBg
      Case Else
        Debug.WriteLine("Rule " & i.ToString & " " & docStyleRules.item(i).selectorText)
    End Select

  Next i

  If (isRefresh) Then  
    Me.myRefresh(curNode)
  End If

End Sub
0 голосов
/ 08 июня 2010

Я обнаружил, что сгенерированные теги с атрибутом класса не применяют их стили.

Это мой обходной путь, который выполняется после создания документа:

public static class WebBrowserExtensions
{
    public static void Redraw(this WebBrowser browser)
    {
        string temp = Path.GetTempFileName();
        File.WriteAllText(temp, browser.Document.Body.Parent.OuterHtml,
            Encoding.GetEncoding(browser.Document.Encoding));
        browser.Url = new Uri(temp);
    }
}
0 голосов
/ 01 апреля 2010

Сложно сказать, если вы не отправите ссылку на это.

но обычно лучший метод для выполнения связанных со стилем вещей заключается в том, что у вас уже есть css на странице, а в вашем коде c # вы только добавляете идентификаторы или классы к элементам, чтобы увидеть эффекты стилей.

...