1

我的 html 源代码中有以下行:

<input class="phone" name="site_url" type="text" placeholder="Enter Your Website URL">

当我使用 WebBrowser Control (C#) 导航并将我的站点加载到 HtmlDocument 对象,然后循环遍历每个 HtmlElement 时,当我到达上面的输入元素时:

我无法获取占位符属性。GetAttribute("placeholder") 返回 ""。我检查了 OuterHtml/InnerHtml 字段并注意到占位符属性是用“”复制的,而其他属性不是,此外,我可以检索其他属性(名称、类)。

这是 InnerHtml/OuterHtml 的输出:

<INPUT class=phone placeholder="Enter Your Website URL" name=site_url>

谁能解释为什么会这样以及在这种情况下如何更改占位符?

4

2 回答 2

2

默认情况下,WebBrowser控件以 IE7 兼容模式运行。在该模式下,placeholder不支持属性。因此,首先您需要将其切换到 IE10 模式,方法如下。然后,您需要调用 unmanaged getAttributeNode并获取它value,方法如下:

bool FindElementWithPlaceholder(HtmlElement root, string placeholder, ref HtmlElement found, ref string value)
{
    foreach (var child in root.Children)
    {
        var childElement = (HtmlElement)child;
        dynamic domElement = childElement.DomElement;
        dynamic attrNode = domElement.getAttributeNode(placeholder);
        if (attrNode != null)
        {
            string v = attrNode.value;
            if (!String.IsNullOrWhiteSpace(v))
            {
                value = v;
                found = childElement;
                return true;
            }
        }
        if (FindElementWithPlaceholder(childElement, placeholder, ref found, ref value))
            return true;
    }
    return false;
}

// ...

HtmlElement element = null;
string value = null;
if (FindElementWithPlaceholder(this.WB.Document.Body, "placeholder", ref element, ref value))
    MessageBox.Show(value);

此代码已通过 IE10 测试。

[已编辑]placeholder即使未实施WebBrowser Feature Control ,您仍然可以使用上述代码检索 的值。但是,placeholder在这种情况下不会在视觉上起作用,因为文档不会处于 HTML5 模式。

[编辑]也许,我终于明白你想要什么了。试试这个代码,看看它是否这样做。您仍然需要功能控制和 DOCTYPE 来启用 HTML5。

HTML: <!doctype html><html><input class=phone placeholder=\"Enter Your Website URL\" name=site_url></html>

HtmlElement element = null;
string oldValue = null;
string newValue = "New Value";
FindElementWithPlaceholder(this.webBrowser1.Document.Body, "placeholder", ref element, ref value, newValue);

bool FindElementWithPlaceholder(HtmlElement root, string placeholder, ref HtmlElement found, ref string oldValue, string newValue)
{
    foreach (var child in root.Children)
    {
        var childElement = (HtmlElement)child;
        dynamic domElement = childElement.DomElement;
        dynamic attrNode = domElement.getAttributeNode(placeholder);
        if (attrNode != null)
        {
            string v = attrNode.value;
            if (!String.IsNullOrWhiteSpace(v))
            {
                domElement.removeAttributeNode(attrNode);
                domElement.setAttribute(placeholder, newValue);
                // a hack to make IE10 to render the new placeholder  
                var id = domElement.getAttribute("id");
                var uniqueId = Guid.NewGuid().ToString();
                domElement.setAttribute("id", uniqueId);
                var html = domElement.outerHTML;
                domElement.outerHTML = html;
                var newElement = root.Document.GetElementById(uniqueId);
                domElement = newElement.DomElement;
                if (String.IsNullOrEmpty(id))
                    domElement.removeAttribute("id");
                else
                    domElement.setAttribute("id", id);
                found = newElement;
                oldValue = v;
                return true;
            }
        }
        if (FindElementWithPlaceholder(childElement, placeholder, ref found, ref oldValue, newValue))
            return true;
    }
    return false;
}
于 2013-08-26T18:32:47.550 回答
1

HtmlElement exposes only those attributes that are common to all elements, leaving out those that only apply to certain types of elements;

HtmlElement.GetAttribute is identical to IHTMLElement::getAttribute(strAttributeName, 0)

There are some change on how getAttribute is working related to Internet Explorer 8, check Remarks section. To resolve this you can do manual parsing for InnerHtml to extract that custom placeholder attribute.

于 2013-08-26T14:53:42.967 回答