WebBrowser isn't working - c#

I have this code:
This is a button press:
int part = 0;
web.Navigate(loginURL.Text + "/auth/login");
wait.Enabled = true;
This is a timer "wait", with interval set to 6000:
if (part == 0)
{
part = 2;
web.Document.GetElementById("idLoginUserName").SetAttribute("value", user);
web.Document.GetElementById("idLoginPassword").SetAttribute("value", pass);
web.Document.GetElementById("idLoginBtn").InvokeMember("click");
}
if (part == 2)
{
web.Navigate(fullURL.Text);
part = 3;
}
if (part == 3)
{
web.Document.GetElementById("title").SetAttribute("value", title.Text);
}
if (part == 4)
{
web.Navigate("www.vbulletin.com/forum/auth/logout");
part = 5;
}
if (part == 5)
{
part = 0;
web.Navigate(loginURL.Text + "/auth/login");
}
The button press works fine, however:
web.Document.GetElementById("idLoginUserName").SetAttribute("value", user);
web.Document.GetElementById("idLoginPassword").SetAttribute("value", pass);
web.Document.GetElementById("idLoginBtn").InvokeMember("click");
does nothing. The text isn't changed, the button isn't clicked, etc. I've checked and double checked the IDs and it's right.
The loginURL.Text is this

My guess you try to access the document before navigation is completed, this works for me...
web.DocumentCompleted += (s, e) =>
{
web.Document.GetElementById("idLoginUserName").SetAttribute("value", user);
web.Document.GetElementById("idLoginPassword").SetAttribute("value", pass);
web.Document.GetElementById("idLoginBtn").InvokeMember("click");
};
web.Navigate("http://www.vbulletin.com/forum/auth/login");

You are not obliged to do everything using C#. If you treat the embedded web page as a black box fro the point of view of your app, you can give it internal behaviours using scripts, and jQuery makes this sort of thing short, sweet and very legible for those who come after, with the added benefit of not polluting application logic with functionally trivial but frequently complex UI behaviour code.
$(function(){
$("#idLoginUserName").val(user);
$("#idLoginPassword").val(password);
$("#idLoginBtn").click();
});

Related

Setting parent button disabled?

So i have a script that creates buttons, and a script that makes these buttons interactable on certain scenarios.
Problem is, in the script that creates the buttons, 2 of the buttons it creates have more child buttons underneath them. With my following code i can easily make those childbuttons interactable whenever i want, but it wont recognize the parents. I realize why (because my list checks for childs) but I have no clue on how to fix this. Make a second list for the parent buttons or? Code is below.
MenuButton[] MenuButtons = _selectionEditMenuPanel.GetComponentsInChildren<MenuButton>(true);
for (int i = 0; i < MenuButtons.Length; i++)
{
if (MenuButtons[i].name == "edit_group" || MenuButtons[i].name == "edit_ungroup")
{
if (_selection.SelectedPageObject.IsGroup())
{
MenuButtons[i].GetComponent<MenuButton>().menuButton.GetComponent<TestButton>().Interactable = true;
if (!((PageObjectGroup)_selection.SelectedPageObject).IsTempGroup)
{
MenuButtons[i].title.text = TranslationSystem.Request("edit_ungroup");
MenuButtons[i].name = "edit_ungroup";
}
else
{
MenuButtons[i].title.text = TranslationSystem.Request("edit_group");
MenuButtons[i].name = "edit_group";
}
}
else
{
MenuButtons[i].title.text = TranslationSystem.Request("edit_group");
MenuButtons[i].name = "edit_group";
MenuButtons[i].GetComponent<MenuButton>().menuButton.GetComponent<testButton>().Interactable = false;
}
}
if (MenuButtons[i].name == "edit_crop")
{
//Only make crop button interactive when pageobject bitmap is selected
MenuButtons[i].GetComponent<MenuButton>().menuButton.GetComponent<testButton>().Interactable = _selection.SelectedPageObject is PageObjectBitmap;
}
//TODO Make this work with edit align? It works with other buttons.
if (MenuButtons[i].name == "edit_align")
{
if (!_selection.SelectedPageObject.IsGroup())
{
MenuButtons[i].GetComponent<MenuButton>().menuButton.GetComponent<testButton>().Interactable = false;
}
else
{
MenuButtons[i].GetComponent<MenuButton>().menuButton.GetComponent<testButton>().Interactable = true;
}
}
It works for everything except the last check, edit_align(this is a button with childs underneath it) I'll post the general setup of the button creating script below, but NOTE: I cant edit that scripts, it's not mine so please don't advise me to edit that.
private static MenuItem _selectionEditMenu = new MenuItem(Resources.Load<Sprite>("Edit_128"))
{ new MenuItem(Resources.Load<Sprite>("Sprites/Icons/Align_Left_1_128"), "edit_align", true, true, null)
{
new MenuItem(Resources.Load<Sprite>("Sprites/Icons/Distribute_Horizontally_128"), "edit_align_distribute_evenly"
new MenuItem(Resources.Load<Sprite>("Sprites/Icons/Uniform_Height_128"), "edit_align_uniform_height"
I can reach the edit_align_Distribute_evenly & the Uniform height, but not the parent above called: edit_align.
NOTE: I left away some syntax etc cause of company names in there. So don't worry about syntax not being correct.
Thanks, every help is highly appreciated.

Way to format Form with dynamic text fields c#

Right, so I have 13 textboxes with corresponding labels that are assigned after a user decides the name from a different form (instantiated by the 'Add field...' button). The issue arises when the user wishes to delete a textbox with previously entered data, as this results in an empty space where the textbox and label originally were as visualized by the following image:
My question is: how do I make it so that when a user chooses to delete a textbox, the textbox-label pair(s) that follow it replace the deleted textbox AND shift the remaining textboxes accordingly.
Textbox-label pairs in designer:
I've thought about this problem intensively over the past few days, and have concluded that with my current knowledge of C# I am limited to solving this issue with a horrendously tedious amount of if-statements (talking hundreds - thousands here). Any and all help would be appreciated!
Current code on the X-button for first textbox-label pair:
private void xButton1_Click(object sender, EventArgs e)
{
label14.Text = "";
textBox1.Text = "";
if (label14.Text.Equals(""))
{
label14.Visible = false;
textBox1.Visible = false;
xButton.Visible = false;
label14.Text = "";
textBox1.Text = "";
}
if (!textBox2.Text.Equals(""))
{
label14.Text = label15.Text;
textBox1.Text = textBox2.Text;
}
if (!textBox2.Text.Equals("") && (textBox3.Text.Equals("")))
{
label15.Visible = false;
textBox2.Text = "";
textBox2.Visible = false;
xButton2.Visible = false;
}
}
One simple thing you could do is give all your "dynamic" controls (label, textbox, button) a similar value in their Tag property (in my example, I used the string "dynamic" for all the control Tags. This enables you to query for them easily.
Next, you could follow the logic that, anytime you delete some controls, you move all controls below the deleted ones up a distance equal to the height of the control being deleted plus whatever padding you have between the controls.
For example, when a user clicks the X button, since you know the value of the Bottom of the control that's being deleted, you could find all controls that had a matching Tag property whose Top is greater than the x button Bottom, and you can move them up.
Here's an example (this assumes that all your X buttons are mapped to this same click event):
private void buttonX_Click(object sender, EventArgs e)
{
// This is represents the distance between the bottom
// of one control to the top of the next control
// Normally it would be defined globally, and used when you
// lay out your controls.
const int controlPadding = 6;
var xButton = sender as Button;
if (xButton == null) return;
var minTopValue = xButton.Bottom;
var distanceToMoveUp = xButton.Height + controlPadding;
// Find all controls that have the Tag and are at the same height as the button
var controlsToDelete = Controls.Cast<Control>().Where(control =>
control.Tag != null &&
control.Tag.ToString() == "dynamic" &&
control.Top == xButton.Top)
.ToList();
// Delete the controls
controlsToDelete.ForEach(Controls.Remove);
// Get all controls with the same tag that are below the deleted controls
var controlsToMove = Controls.Cast<Control>().Where(control =>
control.Tag != null &&
control.Tag.ToString() == "dynamic" &&
control.Top > minTopValue);
// Move each control up the specified amount
foreach (var controlToMove in controlsToMove)
{
controlToMove.Top -= distanceToMoveUp;
}
}

Lightswitch export all rows to CSV

I am using c# and VS2012 on a lightswitch web-application,
I wish to export my data to CSV (on a search screen!), but can't reach any POC,
As i understand there are 2 main problems - a savefiledialog must be caused directly from a user button and in it must happened in the main dispatcher,
I used this code :
partial void mySearchScreen_Created()
{
var CSVButton = this.FindControl("ExportToCSV");
CSVButton.ControlAvailable += ExportCSV_ControlAvailable;
}
private void ExportCSV_ControlAvailable(object sender, ControlAvailableEventArgs e)
{
this.FindControl("ExportToCSV").ControlAvailable -= ExportCSV_ControlAvailable;
Button Button = (Button)e.Control;
Button.Click += ExportCSV_Click;
}
private void ExportCSV_Click(object sender, System.Windows.RoutedEventArgs e)
{
Microsoft.LightSwitch.Details.Client.IScreenCollectionProperty collectionProperty = this.Details.Properties.mySearch;
var intPageSize = collectionProperty.PageSize;
//Get the Current PageSize and store to variable
collectionProperty.PageSize = 0;
var dialog = new SaveFileDialog();
dialog.Filter = "CSV (*.csv)|*.csv";
if (dialog.ShowDialog() == true) {
using (StreamWriter stream = new StreamWriter(dialog.OpenFile())) {
string csv = GetCSV();
stream.Write(csv);
stream.Close();
this.ShowMessageBox("Excel File Created Successfully. NOTE: When you open excel file and if you receive prompt about invalid format then just click yes to continue.", "Excel Export", MessageBoxOption.Ok);
}
}
collectionProperty.PageSize = intPageSize;
//Reset the Current PageSize
}
private string GetCSV()
{
StringBuilder csv = new StringBuilder();
int i = 0;
foreach (var orderRow_loopVariable in mySearch) {
var orderRow = orderRow_loopVariable;
////HEADER
if (i == 0) {
int c = 0;
foreach (var prop_loopVariable in orderRow.Details.Properties.All().OfType<Microsoft.LightSwitch.Details.IEntityStorageProperty>()) {
var prop = prop_loopVariable;
if (c > 0) {
csv.Append(",");//Constants.vbTab
}
c = c + 1;
csv.Append(prop.DisplayName);
}
}
csv.AppendLine("");
////DATA ROWS
int c1 = 0;
foreach (var prop_loopVariable in orderRow.Details.Properties.All().OfType<Microsoft.LightSwitch.Details.IEntityStorageProperty>()) {
var prop = prop_loopVariable;
if (c1 > 0) {
csv.Append(",");//Constants.vbTab
}
c1 = c1 + 1;
csv.Append(prop.Value);
}
i = i + 1;
}
if (csv.Length > 0) {
return csv.ToString(0, csv.Length - 1);
} else {
return "";
}
}
This works, but it only get's me the first page items,
On another thing i had to do i solved that problem by using this code :
this.DataWorkspace.myDataContextData.MySearch(...).Execute();
Yet trying that instead of just using 'MySearch' gives me the following error :
t is not valid to call Execute() on a different Dispatcher than the ExecutableObject's Logic Dispatcher.
Why is it so difficult to do such a basic thing related to data (export to csv/excel) on a system build for handling data ?
Any ideas ?
The simplest workaround if this is the only use of the search screen would be to turn off paging. To do this go to the screen designer, highlight the query on the left, and in properties uncheck 'support paging.'
I'm not sure what the limitations are, but you can run some code in a different dispatcher using:
this.Details.Dispatcher.BeginInvoke(() =>
{
//This runs on main dispatcher
});
I don't think there's anything wrong with your code, but I've noticed that it takes a while to reset the page size on a large collection, in which time the rest of your code continues to execute. I think that's why you only get the first page. The only solution I've found is to wait.
When the "File Download - Security Warning" dialog pops up, keep an eye on the 'busy' indicator on the screen's tab and also the 'Page x of y' status at the bottom of the grid if you can see it. Only when the busy indicator has gone and the status just says 'Page' should you click OK to continue.
I haven't figured out a way of doing this programmatically so it's not a very helpful feature unless you have a very tightly controlled user population. But if it's just you and a couple of power users, it is workable. I'm also not sure if this has been improved on in versions after VS2012.
There can be a downside to the other answer of taking the paging off the query entirely. I've tried that workaround when the grid collection was being displayed in a modal window and the window became uncloseable if there were too many rows in the grid.
Phil

C# DataGridView CellClick Returning Previous Index on Click

I have the following code:
private void dgv_Checks_CellClick(object sender, DataGridViewCellEventArgs e)
{
DoThis();
if (e.RowIndex < 0)
return;
if (dgv_Checks.CurrentCell.OwningColumn.Name == "CopyBalance")
dgv_Checks.Rows[e.RowIndex].Cells["CheckAmountColumn"].Value = dgv_Checks.Rows[e.RowIndex].Cells["AccountBalanceColumn"].Value;
// ****** THIS IS WHERE I AM HAVING ISSUES ******
if (e.RowIndex > -1 && dgv_Checks.Columns[e.ColumnIndex].Name == "SearchColumn")
{
var acctno = dgv_Checks.Rows[e.RowIndex].Cells["AccountNumberColumn"].Value.ToString().Trim();
if (acctno.Length == 7)
{
var acctname = GetAccountName(acctno);
if (acctname.Trim().Length > 0)
{
dgv_Checks.Rows[e.RowIndex].Cells["NameColumn"].Value = acctname;
dgv_Checks.Rows[e.RowIndex].Cells["AccountBalanceColumn"].Value = GetAccountBalance(acctno);
}
else
{
AccountSearchScreen(dgv_Checks.CurrentRow);
}
}
else
{
AccountSearchScreen(dgv_Checks.CurrentRow);
}
}
dgv_Checks.Rows[e.RowIndex].Cells["CheckAmountColumn"].Value = dgv_Checks.Rows[e.RowIndex].Cells["AccountBalanceColumn"].Value;
}
When it reaches this line:
if (e.RowIndex > -1 && dgv_Checks.Columns[e.ColumnIndex].Name == "SearchColumn")
I am getting back the previous cell's index so I am always 1 click behind. Am I not using the right event? I just want to capture a button click and only that one in the "SearchColumn".
Thanks as usual.
If I recall correctly, it has nothing to do with the handler code, and something to do with other page events, master pages, validation, etc. Something is hijacking your request somewhere in the .net framework that causes it to get delayed, but I can't remember where...
Take your gridview and datasource, and put them in a separate file with no master pages or other confounding factors and see if the problem goes away.
If it is now working normally, either add in components from your original page until you can replicate the problem again, or go back to your original page and step through everything it does. This has happened to me at least twice, and all I can remember is that it's something that seems completely unrelated.
Not only have I provided a fairly useless answer, but I've demonstrated once again why I should really keep a (b)log of this crap...

Convert C# to clientside Javascript

I have an Asp.Net page with a list of options accompanied by a checkbox in a ListView control. I have applied Paging using the paging control. However I want to maintain the status of the checkboxes across the various paged pages of the ListView. I have done this with the following code
private List<int> IDs
{
get
{
if (this.ViewState["IDs"] == null)
{
this.ViewState["IDs"] = new List<int>();
}
return (List<int>)this.ViewState["IDs"];
}
}
protected void AddRowstoIDList()
{
int checkAction = 0;
foreach (ListViewDataItem lvi in lvCharOrgs.Items)
{
CheckBox chkSelect = (CheckBox)lvi.FindControl("chkSelect");
if ((((chkSelect) != null)))
{
int ID = Convert.ToInt32(lvCharOrgs.DataKeys[lvi.DisplayIndex].Value);
if ((chkSelect.Checked && !this.IDs.Contains(ID)))
{
this.IDs.Add(ID);
checkAction += 1;
}
else if ((!chkSelect.Checked && this.IDs.Contains(ID)))
{
this.IDs.Remove(ID);
}
}
}
}
protected void lvCharOrgs_ItemDataBound(object sender, ListViewItemEventArgs e)
{
ListViewDataItem lvi = (ListViewDataItem)e.Item;
if ((lvi.ItemType == ListViewItemType.DataItem))
{
// Find the checkbox in the current row
CheckBox chkSelect = (CheckBox)lvi.FindControl("chkSelect");
// Make sure we're referencing the correct control
if ((chkSelect) != null)
{
// If the ID exists in our list then check the checkbox
int ID = Convert.ToInt32(lvCharOrgs.DataKeys[lvi.DisplayIndex].Value);
chkSelect.Checked = this.IDs.Contains(ID);
}
}
if (Profile.proUserType == "basic")
{//basic account so no choice of charity
((CheckBox)e.Item.FindControl("chkSelect")).Checked = true;
((CheckBox)e.Item.FindControl("chkSelect")).Enabled = false;
}
}
Now I have a CustomValidator control which checks to ensure between 3 & 5 records have been selected. If this is true the page is valid and processed. If it is not the case (eg less than 3 or more than 5) the page is Invalid and the CustomValidator throws up a label to notify of this fact.
I use the following code on the serverside to implement this.
protected void lvCharOrgsValidator_ServerValidate(object source, ServerValidateEventArgs args)
{// Custom validate lvCharOrgs
//update selected rows
AddRowstoIDList();
//get count and verify is correct range
int counter = this.IDs.Count;
args.IsValid = (counter >=3 && counter <=5) ? true : false;
}
This all works fine except I need to implement a 'ValidatorCallout' extender from the AJAX Control Toolkit. However this doesn't work with CustomValidators unless they implement clientSide validation. Thus I need to convert the 'lvCharOrgsValidator_ServerValidate' method to a clientside JavaScript function.
Hope this clarifies my requirements.
What does the following do?
AddRowstoIDList();
Something like the following is a start, but will need more details on the above method to provide a working answer
function validateRowCount(sender, args) {
//update selected rows
AddRowstoIDList(); // Does this add row indexes to an array?
//get count and verify is correct range
var counter = IDList.length;
args.IsValid = (counter >=3 && counter <=5);
}
It might be worth looking at Script# for a longer term solution, if you're planning on doing a lot of conversion.
EDIT:
now I can see the AddRowstoIDList() method, to do this on the client-side will be slightly different. Firstly, get a reference to the DOM element that is rendered for lvCharOrgs. Probably the most straightforward way to do this in vanilla JavaScript would be to put the JavaScript function in the page and use the server tags to get the rendered ClientID.
function validateRowCount(sender, args) {
var lvCharOrgs = document.getElementById('<%= lvCharOrgs.ClientID %>');
var checkboxes = lvCharOrgs.getElementsByTagName('input');
var len = checkboxes.length;
var counter = 0;
for(var i =0; i < len; i++) {
if (checkboxes[i].type == "checkbox" && checkboxes[i].checked) counter++;
}
args.IsValid = (counter >=3 && counter <=5);
}
Should work something like this - Working Demo
add /edit to the URL if you want to see the code
If you change int to var, your code is valid JavaScript. (But since it depends on other functions and objects you need to convert those as well.) Also if you're using the c# 3.5 compiler it will stay valid C# even with var instead of int.
Probably not what you want, but there is jsc:
"Web 2.0 hype? Want build better web
sites, but javascript is too hard? No
real IDE? Maybe you should try jsc.
The web app can be built within Visual
Studio 2008 or any other c# compliant
IDE, and then the application
magically appears. You should think of
it as a smart client. Precompile your
c# to javascript with jsc! As an
option instead of using IIS and
asp.net, you could get away by using
apache, with mysql and php."
Have a look at this article. It applies to asp.net mvc, but it also covers some basics and you might be able to do something similar for asp.net. In particular, you might find the jquery remote validation attributes shown in the article useful for what you intend to do.
SharpKit converts C# to client side javascript.
https://sharpkit.github.io/
Well, you can always include your own javascript with custom validators. Here is a link to an article that introduces adding javascript to a validator. You just have to write your own javascript, really.
I heard about a cross-compiler from c# (or was it IL?) to JavaScript but unfortunatly do not remember the name anymore, but a google-search turned up stuff like this: http://jsc.sourceforge.net/

Categories