Im trying to submit a private message in a webforum through C#.
I can fill in every component except for the message box itself:
nk
The usual method of setting the innertext element of the textarea does nothing at all, it works for the rest of the page but not this?? I have no idea why and i can confirm the code is correctly identifying this area.
I can only imagine something else truly controls the display and submission value.
I have found :
When I set the value to anything but 0, the message will post but the text is missing each time.
Any ideas?
I don't know what is your favorite method to access a web page, but you can create a dummy WebBrowser form, then use a function like it:
void SetText(string attribute, string attName, string value)
{
HtmlElementCollection tagsCollection = webBrowser1.Document.GetElementsByTagName("input");
foreach (HtmlElement currentTag in tagsCollection)
{
if (currentTag.GetAttribute(attribute).Equals(attName))
currentTag.SetAttribute("value", value);
}
}
void CheckBox(string attribute, string attName, string value)
{
// Get a collection of all the tags with name "input";
HtmlElementCollection tagsCollection = webBrowser1.Document.GetElementsByTagName("input");
foreach (HtmlElement currentTag in tagsCollection)
{
if (currentTag.GetAttribute(attribute).Equals(attName))
currentTag.SetAttribute("checked", value);
}
}
void ClickButton(string attribute, string attName)
{
webBrowser1.Document.GetElementsByTagName("input");
HtmlElementCollection col = webBrowser1.Document.GetElementsByTagName("button");
foreach (HtmlElement element in col)
{
if (element.GetAttribute(attribute).Equals(attName))
{
element.InvokeMember("click");
}
}
}
Related
I want to change of a ContentControl using Word.Interop. It works with a ContentControl of Type Text. But it fails with a ContentControl of type wdContentControlDropdownList.
Error message something like "You are not allowed to change because the field is protected".
Is there any way to change the active item of a DropDownList?
private void setstatus(string status)
{
ContentControls ccList;
ccList = this.activeDocument.SelectContentControlsByTitle("Status");
ContentControl cc = ccList[1];
// works with wdContentControlText
// fails with wdContentControlDropdownList
cc.Range.Text = status;
}
Finally I found a working solution.
private void setstatus(string value)
{
ContentControls ccList;
ccList = activeDocument.SelectContentControlsByTitle("Status");
ContentControl cc = ccList[1];
// search all list entries and select the required item
foreach (ContentControlListEntry ccl in cc.DropdownListEntries)
{
if (ccl.Text == value)
{
ccl.Select();
break;
}
}
}
Is there a way to access a group of controls in ASP.NET somehow?
In jQuery you can access multiple elements using a class="somegroup" like
$('.somegroup')...
In ASP.NET I understand I can access an element or control using the ID, but is there a way to access multiple controls or elements at once?
For example, let's say I have this in design view:
<asp:Label ID="label1" CssClass="someclass"></asp:Label>
<asp:Label ID="lbl" CssClass="someclass"></asp:Label>
<asp:Label ID="lb2" CssClass="someclass"></asp:Label>
Now I want to turn the visibility off on all of them.
Instead of doing this:
label1.Visible = false;
lbl.Visible = false;
lb2.Visible = false;
Is there an equivalent to this?
someclass.Visible = false;
Is there possibly a different tag property I could be using?
using asp.net and C#
You may write your own function, pass a string class into it (and optionally a parent control or form) then loop thru Controls collection checking for the CssClass property and making needed modifications for matched controls.
Something like
void hide(Control el, string cssClass) {
foreach (WebControl c in el.Controls)
{
if (c.CssClass == cssClass)
{
c.Visible = false;
}
}
}
and call
hide(this, "someclass");
public void Apply(string selector, Control parent, Action<WebControl> a)
{
if (selector.StartsWith("."))
{
foreach(WebControl wc in parent.Controls)
{
if (wc.CssClass == selector.Substring(1))
{
a(wc);
if (wc.HasControls())
{
Apply(selector,wc,a);
}
}
}
}
if (selector.StartsWith("#"))
{
foreach (WebControl wc in parent.Controls)
{
if (wc.ID == selector.Substring(1))
{
a(wc);
return;//no need to search any further.
}else
{
if (wc.HasControls())
{
Apply(selector, wc, a);
}
}
}
}
}
Maybe this will help?
then you can do this:
Apply(".SomeClass", this, a => a.CssClass="SomethingElse");
There is no baked-in syntax for doing a selector-type operation in C#.
You can however write your own loop to do this, like this:
private void SetAllLabelsWithCssClassValueToInvisible(Control parentControl,
string className)
{
foreach(Control childControl in parentControls.Controls)
{
// Try to cast control to a label, null if it fails
var label = childControl as Label;
// Check to see if we successfully cast to label or not
if(label != null)
{
// Yes, it is a label
// Does it have the correct CssClass property value?
if(label.CssClass == className)
{
// Update the Visible property to false
label.Visible = false;
}
}
}
}
Note: Obviously you can expand/improve upon this notion and make it fit your needs, just a proof of concept that is very specific for Label controls with a particular CssClass value and the Visible property.
Internally, the jQuery Sizzle engine is doing this looping for you.
I have a collection of checkbox some 40-50 nos and i have set a attribute 'attr-ID' for each checkbox which is a unique value ID in database. how can i get the control by attribute name in c# code. I want to check some of the checkbox according to dB values on page load event.
<input type="checkbox" id="rdCervical" attr-ID='111' runat='server' />
Is this what you want?
protected void Page_Load(object sender, EventArgs e)
{
var cb = FindControlByAttribute<HtmlInputCheckBox>(this.Page, "attr-ID", "111");
}
public T FindControlByAttribute<T>(Control ctl, string attributeName, string attributeValue) where T : HtmlControl
{
foreach (Control c in ctl.Controls)
{
if (c.GetType() == typeof(T) && ((T)c).Attributes[attributeName]==attributeValue)
{
return (T) c;
}
var cb= FindControlByAttribute<T>(c, attributeName, attributeValue);
if (cb != null)
return cb;
}
return null;
}
if (rdCervical.Attributes["attr-ID"] != null)
{
string id = rdCervical.Attributes["attr-ID"];
rdCervical.Checked = true;
}
I assume you are adding the checkboxes programatically. In that case, make a container <div id="checkContainer" runat="server"></div> and put all your checkboxes inside it. Then just use checkContainer.InnerHtml and parse that code with this library. You can then easily use the library API to find elements by attribute, I think the method was SelectNodes
Without this library, there is no easy way to navigate through HTML elements from code.
How can I set text into a ControlType.Document element using the System.Windows.Automation?
The ValuePattern is not available for Document ControlType and TextPattern doesn't allow setting of new values.
This does not work:
automationElement.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern)
.setValue(value);
I found an ugly way with this method:
private void InsertTextIntoAutomationElement(AutomationElement element, string value) {
object valuePattern = null;
if (!element.TryGetCurrentPattern(ValuePattern.Pattern, out valuePattern)) {
element.SetFocus();
Thread.Sleep(100);
SendKeys.SendWait("^{HOME}"); // Move to start of control
SendKeys.SendWait("^+{END}"); // Select everything
SendKeys.SendWait("{DEL}"); // Delete selection
SendKeys.SendWait(value);
} else{
element.SetFocus();
((ValuePattern)valuePattern).SetValue(value);
}
}
So I have this Silverlight application that calls some reports(.rdlc) via HTML form submit.
This form is universal, so I use it to call all reports with it.
Now I want to clear the input elements in it everytime the form has been submited.
So I want a clear form everytime I want to call a new report with no children in it.
Can anyone explain why this is not working when there are more than 5(or any larger amount of inputs) inputs in the form?
public static void RemoveInputsFromForm(HtmlElement Form)
{
if (HtmlPage.Document.GetElementById(Form.Id) != null)
{
foreach (HtmlElement element in Form.Children)
{
if (element.Id != string.Empty)
{
element.Parent.RemoveChild(element);
}
}
}
}
The form has it's ID and every input has an ID, it removes some inputs randomly, others stay in the form.
This is the method that inserts the input elements into that form:
public static void AddInputToForm(HtmlElement Form, string Name, object Data)
{
if (Data != null && Data.ToString() != string.Empty)
{
var input = HtmlPage.Document.CreateElement("input");
input.SetProperty("type", "hidden");
input.SetProperty("value", Data.ToString());
input.SetProperty("name", Name);
input.SetProperty("id", Name);
Form.AppendChild(input);
}
}
This is the method that I use now to remove form children, it is the same as AddInputToForm method only that it removes inputs
public static void RemoveInputFromForm(HtmlElement Form, string Name)
{
if (HtmlPage.Document.GetElementById(Name) != null)
{
Form.RemoveChild(HtmlPage.Document.GetElementById(Name));
}
}
This is the method that gets my form
public static HtmlElement GetForm(string formUrl)
{
//in the html that holds the silverlight object, you must have a form named "reportform"
//<form id="reportform" action="" method="post" target="_blank" style="visibility: collapse" />
HtmlElement functionReturnValue = null;
//set form
functionReturnValue = HtmlPage.Document.GetElementById("reportform");
//set form action
functionReturnValue.SetProperty("action", formUrl);
return functionReturnValue;
}
To reproduce the code (SomeElement is an object with string properties):
//get form
var Form = GetForm(ApplicationUrl + #"Reports\Report.aspx");
//add parameters to form
AddInputToForm(Form, "id1", SomeElement.Id1Value);
AddInputToForm(Form, "id2", SomeElement.Id2Value);
AddInputToForm(Form, "id3", SomeElement.Id3Value);
AddInputToForm(Form, "id4", SomeElement.Id4Value);
AddInputToForm(Form, "id5", SomeElement.Id5Value);
AddInputToForm(Form, "id6", SomeElement.Id6Value);
AddInputToForm(Form, "id7", SomeElement.Id7Value);
AddInputToForm(Form, "id8", SomeElement.Id8Value);
AddInputToForm(Form, "id9", SomeElement.Id9Value);
//submit form
Form.Invoke("submit");
//clean report
RemoveInputFromForm(Form, "id1");
RemoveInputFromForm(Form, "id2");
RemoveInputFromForm(Form, "id3");
RemoveInputFromForm(Form, "id4");
RemoveInputFromForm(Form, "id5");
RemoveInputFromForm(Form, "id6");
RemoveInputFromForm(Form, "id7");
RemoveInputFromForm(Form, "id8");
RemoveInputFromForm(Form, "id9");
So you see I have to remove every child I added with as many calls as there are inputs in the form, I would like to have only one call and clean that form.
Thanks in advance to any given solution.
You should never add or remove elements while inside a foreach loop, as the collection changes and invalidates the loop. Rather add all items to be removed in a separate list and then remove them in a second loop. (I haven't tested it because I do not have relevant sample code, but this is a common mistake with foreach loops.)
List<HtmlElement> toRemove = new List<HtmlElement>();
foreach (HtmlElement element in Form.Children)
{
if (element.Id != string.Empty)
{
toRemove.Add(element);
}
}
foreach (HtmlElement element in toRemove)
{
Form.RemoveChild(element);
}
Alternatively, using your second approach, you can always add all your IDs to a list, and then add a RemoveAllFormInputs() method which loops over these elements.
Peet has provided the correct answer, however some may prefer a Linq based approach that slims the code a litte.
foreach (HtmlElement element in Form.Children
.OfType<HtmlElement>
.Where(e => !String.IsNullOrEmpty(e.Id))
.ToList() )
{
Form.RemoveChild(element);
}