I'm trying to make a simple Facebook client. One of the features should allow the user to post content on the homepage/his profile.
It logs the user in (works fine, all of the elements have got ids on Facebook) and then inserts the data in the corresponding field (works fine as well), but then it needs to click the "Post" button. However, this button doesn't have any id. It only has got a class.
<li><button value="1" class="_42ft _4jy0 _11b _4jy3 _4jy1 selected _51sy" data-ft="{"tn":"+{"}" type="submit">Posten</button></li>
('Posten' is 'Post' on German.)
I've been looking around the internet for a few hours now and tried different solutions. My most current solution is to search the item by it's inner content ("Posten") and then invoke it. Doesn't work. It inserts the text but doesn't invoke the button. Here's the code:
private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (postHomepage)
{
webBrowser1.Document.GetElementById("u_0_z").SetAttribute("value", metroTextBox1.Text);
GetButtonByInnerText("Posten").InvokeMember("click");
postHomepage = false;
}
}
HtmlElement GetButtonByInnerText(string SearchString)
{
String data = webBrowser1.DocumentText;
//Is the string contained in the website
int indexOfText = data.IndexOf(SearchString);
if (indexOfText < 0)
{
return null;
}
data = data.Remove(indexOfText); //Remove all text after the found text
//These strings are a list of website elements
//NOTE: These need to be updated with ALL elements from list such as:
// http://www.w3.org/TR/REC-html40/index/elements.html
string[] strings = { "<button" };
//Split the string with these elements.
//subtract 2 because -1 for index -1 for elements being 1 bigger than wanted
int index = (data.Split(strings, StringSplitOptions.None).Length - 2);
HtmlElement item = webBrowser1.Document.All[index];
//If the element is a div (which contains the search string
//we actually need the next item.
if (item.OuterHtml.Trim().ToLower().StartsWith("<li"))
item = webBrowser1.Document.All[index + 1];
//txtDebug.Text = index.ToString();
return item;
}
(This is a quick solution which I edited for my use, not very clean).
What's wrong here?
It does not look like your GetButtonByInnerText() method is searching for the button element correctly.
Here is simple replacement for you to try:
HtmlElement GetButtonByInnerText(string SearchString)
{
foreach (HtmlElement el in webBrowser1.Document.All)
if (el.InnerText==SearchString)
return el;
}
Related
I have an object which is defined as Pane in FlaUInspect with a number of Checkboxes loaded dynamically when the program starts. For a Unit Test I need to loop through all the checkBoxes and find one particular item based upon a string. The code below was first attempt to load the item which does load but it doesn't list all the checkboxes in the Pane.
ListBox seqPanelItems = databaseWindow.FindFirstDescendant(cf => cf.ByAutomationId("sequenceScrollViewer")).AsListBox();
var rdctSeqCheckBox = GetSeqPanelCheckbox(seqPanelItems, "RDCT");
The following code is what loops through the items.
private CheckBox GetSeqPanelCheckbox(ListBox items, string name)
{
for (int i = 0; i < items.Items.Length; i += 1)
{
//if (items[i] is not Label)
//{
// continue;
//}
if (items.Items[i].Name == name)
{
return items.Items[i - 1].AsCheckBox();
}
}
return null;
}
As the code indicates, it needs to find the particular item and return it as a checkbox item but items.Items.Length returns 0.
Below is what FlaUInspect shows.
I am considering this problem closed. I moved the CheckBox and Text to a list box.
I've been working on the past couple of days on a ListView based Music player using NAudio in C#. It's now time for me to start working on the forward/previous functions but I've come to a bit of a bump in the road. I need to select whatever the next item in the listView I have is. However, it is not selected by the user but instead is marked as now playing by a checkmark next to it with the default ListView checkboxes.
Here's what it looks like:
I've got a public string that's accessible by anything; it has the filename of the currently playing track in it. Whenever I click to play a track, I've got a foreach loop that loops through all of the items in this listView (I've got a second listview in another tab that has all the music I click to play from) and if the filename subitem and currentlyPlaying string match, then it checks it. If not, it unchecks.
I've got an event handler in my mainclass for when the playback stops on the track. What's going to go in there will be the logic for the next track. I've got a general idea of what to do but I'm not sure how to go about doing it
Get the index of the item with the check mark next to it
Get the item after it
Retrieve its fileName subitem
Play it
So what would be the way to go about doing this? I'm still a bit confused with listViews and such.
Update: Also, how possible is it to disable the user checking the check box, I've got it down for when it's a double click but what about when the user checks the checkbox themselves?
Update 2: Here's the eventhandler with some scratch code I was working on
public void waveOutDevice_PlaybackStopped(object sender, StoppedEventArgs e)
{
string fileName;
foreach (ListViewItem lvi in playListView.Items)
{
fileName = lvi.SubItems[1].Text;
if(lvi.Checked == true)
{
int finIndex;
lvi.Checked = false;
finIndex = lvi.Index;
//finIndex + 1;
}
}
}
I think you are just about there. all you need to do is something like this:
public void waveOutDevice_PlaybackStopped(object sender, StoppedEventArgs e)
{
string fileName;
foreach (ListViewItem lvi in playListView.Items)
{
fileName = lvi.SubItems[1].Text;
if(lvi.Checked == true)
{
int finIndex;
lvi.Checked = false;
finIndex = lvi.Index;
finIndex++;
if(finIndex < playListView.Count())
{
var nextGuy = playListView.Items[finIndex];
nextGuy.Checked = true;
//Play the file and what not.
}
}
}
}
I'm trying to simply select one string line out a long list strings that are held on a server and seperated with a pipe character. This string is grabbed by a php script and the string line is a list of all the media and folders I have on my server.
In my code I'm getting this information and returning it with the following code:
using (var client = new WebClient())
{
result = client.DownloadString("http://server.foo.com/images/getDirectoryList.php");
}
textBox1.Text = string.Join(Environment.NewLine, result.Split('|'));
And it looks like this:
But when I try to simply click on one of them, my cursor simply just goes to where I've clicked. Like this, I tried to select md-harrier.jpg and my cursor just ends up at the end of jpg:
What I'm really wanting is pictured below. I click on Koala.jpg and the whole thing is highlighted and I have the ability to store the name of what it is I've just clicked on. TO achieve that screen shot I had to click next to Koala.jpg and then drag my mouse along.
Is there anyway I can achieve what I want to achieve?
The key thing to note about this is that I will have no idea how many files will be on the server, nor what they will be called. My php script is grabbing this information and displaying it in my winform text box using the code I have wrote above.
as Simon said you need a ListBox, a ListBox fits here because it allows you to select a line, and you can register to the event of SelectedIndexChanged and store the name that was selected.
to initiate the values do
using (var client = new WebClient())
{
result = client.DownloadString("http://bender.holovis.com/images/getDirectoryList.php");
}
listBox1.Items.AddRange(result.Split('|'));
listBox1.SelectedIndexChanged += new System.EventHandler(this.listBox1_SelectedIndexChanged);
and on the selectedItemChanged:
string currVal;
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
currVal = (string)listBox1.SelectedItem;
}
As you said you have no reason to use TextBox,then by using ListBox you can achieve that in this way;
using (var client = new WebClient())
{
result = client.DownloadString("http://bender.holovis.com/images/getDirectoryList.php");
}
string[] names=result.Split('|');
foreach(string name in names)
{
if(name!="|"&&name!=" ")
{
listbox.Items.Add(name);
}
}
Additionally,if you would like to store selected item in a variable subscribe to ListBox's SelectionChangedEvent and store the selection index in a variable in this way;
int selection=;
private void ListBox1_SelectionIndexChanged(object sender,EventArgs e)
{
selection=ListBox1.SelectedIndex;
}
I have defined a placeholder in my page like this;
<asp:PlaceHolder ID="attrPlaceHolder" runat="server"></asp:PlaceHolder>
I am populating this place holder from a database table using query string productId like this;
// obtain the attributes of the product
DataTable attrTable = CatalogAccess.GetProductAttributes(productId);
// temp variables
string prevAttributeName = "";
string attributeName, attributeValue, attributeValueId;
// current DropDown for attribute values
Label attributeNameLabel;
DropDownList attributeValuesDropDown = new DropDownList();
// read the list of attributes
foreach (DataRow r in attrTable.Rows)
{
// get attribute data
attributeName = r["AttributeName"].ToString();
attributeValue = r["AttributeValue"].ToString();
attributeValueId = r["AttributeValueID"].ToString();
// if starting a new attribute (e.g. Color, Size)
if (attributeName != prevAttributeName)
{
prevAttributeName = attributeName;
attributeNameLabel = new Label();
attributeNameLabel.Text = "<li class=\"txt\">" + attributeName + ":</li>";
attributeValuesDropDown = new DropDownList();
attrPlaceHolder.Controls.Add(attributeNameLabel);
attrPlaceHolder.Controls.Add(attributeValuesDropDown);
}
// add a new attribute value to the DropDownList
attributeValuesDropDown.Items.Add(new ListItem(attributeValue, attributeValueId));
}
However, when inside a button click event, when I loop through this place using visual studio debugging, I saw that the visual studio studio debugger first hit the "attrPlaceHolder.Controls" word in my foreach loop, then secondly comes to 'in' keyword (in foreach loop) but it isn't hitting the first two words (i-e 'Control cnt' in my foreach loop. Here it looks;
protected void ButtonBuyNow_Click(object sender, EventArgs e)
{
// Retrieve the selected product options
string options = "";
foreach (Control cnt in attrPlaceHolder.Controls)
{
if (cnt is Label)
{
Label attrLabel = (Label)cnt;
options += attrLabel.Text;
}
if (cnt is DropDownList)
{
DropDownList attrDropDown = (DropDownList)cnt;
options += attrDropDown.Items[attrDropDown.SelectedIndex] + "; ";
}
}
// Add the product to the shopping cart
ShoppingCartAccess.AddItem(productId, options);
}
Basically I need 'options' variable to be populated but it isn't hitting the foreach loop inside, therefore I am not able to get the 'options' variable populated.
This is a serious problem in my application. Please tell me why I can't get the inside the foreach loop.
NOTE:
please note that this isn't the complete code of my entire page. My rest of the code executes correctly.
why I can't get the inside the foreach loop
Because the list is empty.
Why is the list empty? (Would be the next logical question)
Because, at ASP.Net, dynamically created controls must be re-created at Page_Init in order to exist. When you create them at this stage, the page lifecycle will bind the viewstate and will be ready for use.
If you receive a postback (from the button, for example) and don't recreate them, they simply don't exist.
I need to add a command to right click menu in Word shown after clicking field.
That wasn't a problem:
var ContextMenu = this.Application.CommandBars["Fields"];
button = (Office.CommandBarButton)ContextMenu.Controls.Add(1);
button.Click += new Office._CommandBarButtonEvents_ClickEventHandler(button_Click);
Now I need to get the field user clicked. I tried this:
void button_Click(Office.CommandBarButton Ctrl, ref bool cancel)
{
var currentSelection = Globals.ThisAddIn.Application.ActiveWindow.Selection;
if (currentSelection.Fields.Count > 0)
var field = currentSelection.Fields[1]
//Do some stuff with the field
}
But it will only work if the field is selected, it won't work for example when user just right clicked it without selecting anything or selected only part of fields displayed text.
You can significantly reduce the number of fields you iterate by checking currentSelection.Range.Paragrahs[1].Fields.
I came up with this solution but still looking for something that won't have to iterate throught all fields in document:
public static IEnumerable<Field> GetAllFieldsInSelection(this Selection selection)
{
foreach (Field f in selection.Document.Fields)
{
int fieldStart = f.Code.FormattedText.Start;
int fieldEnd = f.Code.FormattedText.End + f.Result.Text.Count();//field code + displayed text lenght
if (!((fieldStart < selection.Start) & (fieldEnd < selection.Start) |
(fieldStart > selection.End) & (fieldEnd > selection.End)))
{
yield return f;
}
}
}