Using Dynamic CEFSharp with ChromeTabs but AddressChanged is not exposed - wpf

I am making an app that started with the CEFSharp minimal example code and I am using ChromeTabs in Wpf. I have my CEFSharp diverting popup windows into tabs correctly but I am having an issue grabbing the URL of these dynamic CEFSharp windows. For some reason AddressChanged is not exposed for these dynamic windows. I have tried to make use of LoadingStateChanged to place the URL in a textbox but that creates all new issues with the threads. I have spent the past few days trying to get this to work and it is driving me crazy. This is how my new tab is created but it does not expose AddressChanged event.
int counttabs = tbControlRCI.Items.Count-1;
string popURL;
popURL = popup_request;
tbControlRCI = this.etTabCntrlRCI;
//here we should open a new tab and place a new rcibrowser in it and give it the url
RCIBrowser = new ChromiumWebBrowser(popURL);
RCIBrowser.Name = "RCIBrow_" + counttabs;
string shorturl = popURL.Substring(popURL.LastIndexOf("/"), popURL.Length - popURL.LastIndexOf("/"));
ChromeTabs.ChromeTabItem newTabItem = new ChromeTabs.ChromeTabItem
{
Header = shorturl,
Name = "RCITab_" + counttabs,
Content = RCIBrowser
};
LifespanHandler lifeRCI = new LifespanHandler();
RCIBrowser.LifeSpanHandler = lifeRCI;
lifeRCI.popup_request += life_popup_request;
tbControlRCI.Items.Add(newTabItem);
tbControlRCI.SelectedIndex = tbControlRCI.Items.Count - 1;
My XAML only has a ChromeTabsControl that I place all of these dynamic Tabs and Browsers into.
Can anyone show the error of my ways?
EDIT:
Ok, thanks amaitland, I have tried a few different ways to do that and it just does not update for some reason. All I need is a textbox to show the address the Browser is on, so one way is fine. So I tried this:
Binding b = new Binding();
b.Mode = BindingMode.OneWay;
b.Path = new PropertyPath("Address");
b.ElementName = "RCIBrowser";
txtbxRCI.SetBinding(TextBox.TextProperty, b);
Thanks a bunch,
Hometownnerd

Related

TestComplete can't find WinForms object during runtime

I have an application written in WinForms and it contains a single TextBox.
With the TestComplete spy, I can spot the TextBox and its properties but during runtime, this control, in contrast to all the other controls, can't be spotted by its name or any of its other properties.
Why is that and how can I fix it (either on the application side or the testing side)?
This is how the control is defined:
this.myTxtBx.BackColor = System.Drawing.SystemColors.InactiveBorder;
this.myTxtBx.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.myTxtBx.Location = new System.Drawing.Point(74, 25);
this.myTxtBx.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
this.myTxtBx.Name = "myTxtBox";
this.myTxtBx.Size = new System.Drawing.Size(91, 20);
this.myTxtBx.TabIndex = 1;
this.myTxtBx.TextChanged += new
System.EventHandler(this.myTxtBox_TextChanged);
You need to map the object at runtime with objectmapper, give it an alias and use it in your script.
(TC has its own winapp driver protocol that reads the screen very much like W3Cs webdriver that all major browsers support to make automation possible).
Below is a js-function using WIX that finds an objectmapped form and enters a value (Your alias would probably be something like:
Aliases.YourApp.myTxtBx.TextChanged):
function policeIdCheck() {
var nomatch = "GC0000531";
var idnumform = Aliases.LraClient.ContentControl.ActionInfoContainerClearView.ContentControl.ActionInfoContainer.ItemsControl.IDDocNumberForm;
if(idnumform.Exists) {
Log.Message("IDPolice Check");
idnumform.Keys(nomatch);
}
}

Concurrency Error WinForms Binding Source Navigator

I have a form with customer info that needs to be processed one transaction per page. I'm using the binding navigator to manage my pagination.
It works in all but some cases. In the cases where it doesn't work, I have to open a different window to look up information and return it to the main form. Here is the code for that:
// save current work
updateDataTable();
// Open a window and get new customer info
// CurrentCustomer is returned from the opened window
using (SqlConnection cx = new SqlConnection(GetConnectionString()))
{
DataRowView dataRow = (DataRowView)procBindingSource.Current;
dataRow.BeginEdit();
dataRow["CUSTOMER"] = CurrentCustomer;
dataRow.EndEdit();
updateDataItems();
SqlCommand cmd = new SqlCommand(
#" select acct_no from cust_processing where id = #id ", cx);
cmd.Parameters.AddWithValue("#id", (int)dataRow["ID"]);
cx.Open();
var results = cmd.ExecuteScalar();
if (results != null)
{
dataRow.BeginEdit();
dataRow["ACCT_NO"] = results.ToString();
dataRow.EndEdit();
updateDataItems(); <------ CONCURRENCY ERROR
}
}
The error I am getting is a concurrency error. I think that I have more than one version of the row possibly ? I thought I was making sure that I was on the most recent version of the row by calling updateDataTable(). I am the only user so I know I am creating the problem myself.
Here is my update method which is called when I change pages or save and exit or want to write the commit the data:
void updateDataItems()
{
this.procBindingSource.EndEdit();
this.procTableAdapter.Update(xyzDataSet);
xyzDataSet.AcceptChanges();
}
I have tried executing updateDataItems from various places such as after I assign dataRow["ACCT_NO"] = results.ToString() or before and after assigning that.
I'm pretty much down to guess and check so any thoughts, help and advice will be appreciated and +1.
Okay -- so the problem was that I was trying to update the current row from the program and also using the binding navigator. They were not working together properly.
The solution was to add a text box to the form in the forms designer and set visible = false and bind it to ACCT_NO. Once I got the results from my other form, I just needed to set the .text property of the ACCT_NO textbox to the new value and the binding navigator managed all my updates for me correctly.
txtAcct_No.text = results.ToString();

Layout issue with Codename One

At this moment I'm only testing my app in the simulator (as I'm having issues with "Send iOS Build" mentioned in another thread [Errors with Codename One "Send iOS Build" and "Send Android Build")
I'm experiencing some layout issues where it is not making use of the width and height correctly. The elements are left-aligned and there is unused space on the right side. And I need to scroll up and down instead of having everything fit within the visual area. Please see images.
The code are:
private final void show() {
loginSignupForm = new Form("Company", new BoxLayout(0));
Tabs loginSignupTabs = new Tabs();
Style loginSignupStyle = UIManager.getInstance().getComponentStyle("Tab");
prepareAndAddSignupTab(loginSignupTabs, loginSignupStyle);
prepareAndAddLoginTab(loginSignupTabs, loginSignupStyle);
loginSignupForm.add(loginSignupTabs);
loginSignupForm.show();
}
private void prepareAndAddLoginTab(Tabs loginSignupTabs, Style loginSignupStyle) {
loginID = new TextField();
loginPassword = new TextField();
Button loginButton = getLoginButton();
Component[] loginComponents = {
new Label("Email Address"),
loginID,
new Label("Password"),
loginPassword,
loginButton,
};
Container loginContainer = BoxLayout.encloseY(loginComponents);
FontImage loginIcon = FontImage.createMaterial(FontImage.MATERIAL_QUESTION_ANSWER, loginSignupStyle);
loginSignupTabs.addTab("Login", loginIcon, loginContainer);
}
What do I need to changenter code heree to get the elements to:
1. expand to the maximum width (no free space on the right)
2. fit within the visual area (for top-to-bottom)
Please note that I'm coding the elements because I find the (new) GUI Builder quite a challenge to use.
Firstly, don't pass a constant value as an argument to Layouts, coz the values might change in future Codename One updates and this will be difficult for you to debug. new BoxLayout(0) should be new BoxLayout(BoxLayout.Y_AXIS) or simply BoxLayout.y().
The above is where the problem arose but not the only problem because BoxLayout doesn't recognize 0 as a valid argument as it has only 3 which are X_AXIS = 1, Y_AXIS = 2, and X_AXIS_NO_GROW = 3.
If you change the above to use BoxLayout.Y_AXIS, it will work, but from the screenshot above, that's not the best solution.
In conclusion, change your code to below:
private final void show() {
loginSignupForm = new Form("Company", new BorderLayout());
Tabs loginSignupTabs = new Tabs();
Style loginSignupStyle = UIManager.getInstance().getComponentStyle("Tab");
prepareAndAddSignupTab(loginSignupTabs, loginSignupStyle);
prepareAndAddLoginTab(loginSignupTabs, loginSignupStyle);
loginSignupForm.add(BorderLayout.CENTER, loginSignupTabs);
loginSignupForm.show();
}

codenameone Picker Alternative to ComboBox

I am getting my feet wet with Codename One. I have looked into more other options like Xamarin, PhoneGap, Ionic for cross platform but I kinda got hooked with Codename one as it really code once and run anywhere.
I've been going through ui elements and I am kinda blocked on populating a combobox (Alternative is Picker)
Let's say I have stores as value pair (storeId, storeName). I want to display the storeName in Picker but keep storeId as the value reference.
Once the store is selected I would like to pass the storeId to an API call.
Is this possible. This might be very simple question but seems bit difficult to implement (I am really new to mobile).
Thank you.
Our recommendation is to avoid ComboBox. It's a UI pattern that doesn't exist on iOS natively and would feel alien on modern phones. It exists in Codename One.
In this code from the sample above you can get a similar effect to a complex multi-field combo box:
Form hi = new Form("Button", BoxLayout.y());
String[] characters = { "Tyrion Lannister", "Jaime Lannister", "Cersei Lannister"};
String[] actors = { "Peter Dinklage", "Nikolaj Coster-Waldau", "Lena Headey"};
int size = Display.getInstance().convertToPixels(7);
EncodedImage placeholder = EncodedImage.createFromImage(Image.createImage(size, size, 0xffcccccc), true);
Image[] pictures = {
URLImage.createToStorage(placeholder, "tyrion","http://i.lv3.hbo.com/assets/images/series/game-of-thrones/character/s5/tyrion-lannister-512x512.jpg"),
URLImage.createToStorage(placeholder, "jaime","http://i.lv3.hbo.com/assets/images/series/game-of-thrones/character/s5/jamie-lannister-512x512.jpg"),
URLImage.createToStorage(placeholder, "cersei","http://i.lv3.hbo.com/assets/images/series/game-of-thrones/character/s5/cersei-lannister-512x512.jpg")
};
MultiButton b = new MultiButton("Pick A Lanister...");
b.addActionListener(e -> {
Dialog d = new Dialog();
d.setLayout(BoxLayout.y());
d.getContentPane().setScrollableY(true);
for(int iter = 0 ; iter < characters.length ; iter++) {
MultiButton mb = new MultiButton(characters[iter]);
mb.setTextLine2(actors[iter]);
mb.setIcon(pictures[iter]);
d.add(mb);
mb.addActionListener(ee -> {
b.setTextLine1(mb.getTextLine1());
b.setTextLine2(mb.getTextLine2());
b.setIcon(mb.getIcon());
d.dispose();
b.revalidate();
});
}
d.showPopupDialog(b);
});
hi.add(b);
hi.show();
If you insist on using a ComboBox you can use a model to give it any object data you want. Then create a cell render to display the data. This is all discussed in depth in the component section of Codname One's developer guide. Notice that since ComboBox derives from List a lot of the List tips and docs apply to ComboBox.

Printing text in Silverlight that measures larger than page

I have a silverlight application that allows people to enter into a notes field which can be printed, the code used to do this is:
PrintDocument pd = new PrintDocument();
Viewbox box = new Viewbox();
TextBlock txt = new TextBlock();
txt.TextWrapping = TextWrapping.Wrap;
Paragraph pg = new Paragraph();
Run run = new Run();
pg = (Paragraph)rtText.Blocks[0];
run = (Run)pg.Inlines[0];
txt.Text = run.Text;
pd.PrintPage += (s, pe) =>
{
double grdHeight = pe.PrintableArea.Height - (pe.PageMargins.Top + pe.PageMargins.Bottom);
double grdWidth = pe.PrintableArea.Width - (pe.PageMargins.Left + pe.PageMargins.Right);
txt.Width = grdWidth;
txt.Height = grdHeight;
pe.PageVisual = txt;
};
pd.Print(lblTitle.Text);
This simply prints the content of the textbox on the page however some of the notes are spanning larger than the page itself causing it to be cut off. How can I change my code to measure the text and add more pages OR is there a better way to do the above where it will automatically create multiple pages for me?
There are several solutions to your problem, all of them under "Multiple Page Printing Silverlight" on Google. I was having a similar problem and tried most of them. The only one that worked for me was this one:
http://www.codeproject.com/Tips/248553/Silverlight-converting-to-image-and-printing-an-UI
But honestly you should look at Google first and see whether there are better solutions to your specific problem.
Answering your question, there is a flag called HasMorePages that indicates you need a new page. Just type pe.HasMorePages and you will see.
Hope it helps
First you need to work out how many pages are needed
Dim pagesNeeded As Integer = Math.Ceiling(gridHeight / pageHeight) 'gets number of pages needed
Then once the first page has been sent to the printer, you need to move that data out of view and bring the new data into view ready to print. I do this by converting the whole dataset into an image/UI element, i can then adjust Y value accordingly to bring the next set of required data on screen.
transformGroup.Children.Add(New TranslateTransform() With {.Y = -(pageIndex * pageHeight)})
Then once the number of needed pages is reached, tell the printer to stop
'sets if there is more than 1 page to print
If pagesLeft <= 0 Then
e.HasMorePages = False
Exit Sub
Else
e.HasMorePages = True
End If
Or if this is too much work, you can simply just scale all the notes to fit onto screen. Again probably by converting to UI element.
Hope this helps

Resources