MvvmCross : databinding programmatically - windows-phone-7

I think I need to bind data programmatically to solve my problem.
I use a TabHost which hosts 2 Tabs.
I need to load the MvxBindableListView in the second tab when TabHost appears and keep the first tab as default tab.
What I'm doing is starting the second tab activity without problem because I check the process using this code:
protected override void OnViewModelSet()
{
SetContentView(Resource.Layout.Page_ActivityView);
System.Diagnostics.Debug.WriteLine("activityView started");
MvxBindableListView mvxBindableListView = FindViewById<MvxBindableListView>(Resource.Id.mvxBindableListView);
mvxBindableListView.ChildViewAdded += new System.EventHandler<Android.Views.ViewGroup.ChildViewAddedEventArgs>(mvxBindableListView_ChildViewAdded);
}
"activityView started" is displayed in output debugger, but MvxBindableListView.ChildViewAdded event isn't raised, only when I click the second tab.
So I suppose that MvxBindableListView is not databound.
Thanks in advance to help me loading my second tab programmatically.

I think ChildViewAdded is an event that occurs when the ListView is rendered - at that time when it needs to 'draw list items', then it will ask its adapter for child Views for the screen. As you scroll down the list, it will then ask for more child views - but it will also reuse views - so for a simple list you should only ever (hopefully) get N+1 calls on ChildViewAdded for a list which shows N items at one time.
So it's perfectly possible for a list to be databound but never to call ChildViewAdded - that won't get called until the list is 'drawn'
Sadly the Xamarin docs aren't helpful here - http://docs.mono-android.net/monodoc.ashx?link=E%3AAndroid.Views.ViewGroup.ChildViewAdded
Note: if you do actually want to bind programatically, then you can do this to - using Bind() methods and extension methods. However, I haven't expanded on that here - as it doesn't sound like that's actually what you need!

Related

Xamarin custom control in a datatemplate created with CreateContent()

I have implemented a custom DataTemplateSelector according to: GitHub Xamarin Forms.
This allows for a datatemplate to be selected based on an item, which is received through a data binding. This works fine to select a proper datatemplate and render it. However, I am now at a point where I want to add custom controls to this datatemplate (custom buttons). This works on any other page, but for some reason not in this datatemplate.
The relevant lines in the datatemplate:
xmlns:controls="clr-namespace:Universal_ONE.Views.Controls"
<controls:IconButton Command="{Binding RobotLocationSave}"
Image="{StaticResource BoltBlack}"/>
The part the datatemplate is selected and created:
var templateToUse = templateSelector.SelectTemplate(item, null);
View view = (View)templateToUse.CreateContent();
view.BindingContext = bindingContext;
In the catch block I get the error (after calling CreateContent()):
Xamarin.Forms.Xaml.XamlParseException: Position 371:26. Type controls:IconButton not found in xmlns clr-namespace:Universal_ONE.Views.Controls
The problem has to be with the CreateContent(), since using the control outside of this datatemplate works.
EDIT 1
I've created a Minimal Working Example: GitHub.
The datatemplate is now hardcoded, so I'm sure that one is selected.
The same parseexception gets thrown.
I am trying to compile Xamarin.Forms myself so I can debug the framework itself. However, compiling is not going smooth; thus might take a bit longer.
EDIT 2
A bit more info on the MWE:
The MainPage.xaml has the default Xamarin.Forms app code. Below I've added a custom control, which is simply a frame with a label. The text of this label is set via a bindableproperty (not really relevant). Below this control is the datatemplatecontrol added, which in turn calls the datatemplateselector, which returns the datatemplate. This datatemplate contains the same control as the mainpage. Thus the rendered app should have 2 controls. However, in de datatemplatecontrol you can breakpoint on the catch statement (look for my comment). This is where the parseexception will show, which is caused after calling CreateContent() on the datatemplate.
EDIT 3
I've not been clear enough I think. But you have to put a breakpoint on line 41 of datatemplatecontroler.cs. Since the content of the datatemplate is set to null if the createcontent() fails, thus fails gracefully. When hitting the breakpoint you can read the parseexception.
EDIT 4
I've made an issue and a pull request on the Xamarin repository: GitHub. The problem resides with the XamlParser, which has a small bug where it selects the wrong assembly. Inside the issue I've mentioned a workaround which can be used for now.
I try to download your example and run it. When I run to Content = CreateTemplateForItem(ItemTemplate); the program does not report an error, so the program skips the catch method. Here is a screenshot of the runtime:
Then I tried to actively throw an exception in the try statement (throw new Exception();) to make the program enter the catch method, Here is a screenshot of the runtime:

How to implement direct transitions between sibling pages in Xamarin.Forms with ReactiveUI?

I need to implement the routing functionality in Xamarin.Forms application using the ReactiveUI framework.
The following transitions map needs to be implemented:

Above the black arrows show forward transitions (e.g. I go from the Menu to the Order page by clicking on the menu item button), while the red arrows are for Go Back functionality. Please note that Go back should work for both: (a) the "Go back" link in the top navigation bar (b) the hardware «Back» button on the Android devices.
How do I implement the transitions between sibling pages like these:
Menu - Order - Map - Back to the Menu
Menu - Order - Order details - Pin details page - Back to the Map - Back to the Menu
?
P.S. Here is the guide https://www.reactiveui.net/docs/handbook/routing/ I followed recently, so I used GoNext/GoBack commands to implement more simple transitions like Menu - Order - Order details - Back to the Order - Back to the Menu. It does not work well for the described case, as the Back buttons make transitions back to the previous page instead of their parent page in the navigation map.
The NavigateBack command implementation is quite simple in ReactiveUI's RoutingState, it just removes the last element from the RoutingState.NavigationStack, RoutingState.NavigationStack is an instance of ObservableCollection<IRoutableViewModel>.
So in your particular case, you could write your own NavigateBack command implementation that mutates the navigation stack as required by your application domain. You could use a switch block to figure out what page is currently shown in the screen, and then map that page into another page, either newly created or stored in a field or in a Locator.Current. Probably your command will require a more complex canExecute implementation as well.
ReactiveCommand<Unit, IRoutableViewModel> navigateBackDomainAware =
ReactiveCommand.CreateFromObservable(() => {
var currentViewModel = NavigationStack[NavigationStack.Count - 1];
if (currentViewModel is PinDetailsViewModel) {
var mapViewModel = GetMapViewModel();
NavigationStack.Add(mapViewModel); // The navigation.
return Observable.Return(mapViewModel);
} else {
// Handle other pages. You can also put some domain-specific code
// describing the navigation mappings in your application here.
}
});

Coded UI Test - Set UI property not returning (hanging indefinitely)

I am getting crazy with a problem that I found when executing a Visual Studio Coded UI Test.
The scenario is as follows.
I recorded a Coded UI Tests that do the following steps in a Web Application (Microsoft Dynamics CRM 2011):
Login into an application
Navigate into a page
On the page set the selected value of a html combobox
The test is able to do all those steps without a problem, even selecting the value in the combobox.
The web application have a piece of Javascript that is executed when the selected item changes.
if one of the values is selected then an alert message is presented to the user and the application will set the selected item to a default one!
The javascript code look like this:
switch (Xrm.Page.getAttribute("status").getValue()) {
case 3: //Authorised
alert("Please use the method XPTO to update the record status to Authorised!");
Xrm.Page.getAttribute("status").setValue(1);
Xrm.Page.getControl("tatus").setFocus(true);
return false;
The UI Test method that is performing the change in the combobox is as follows:
/// <summary>
/// Select a value in the Status dropdown box
/// </summary>
public void SelectStatus()
{
#region Variable Declarations
HtmlComboBox uIStatusComboBox = this.UIHttpsappWindow200.UIModuleUITEDocument5.UIWorkplaceDashboardsFrame.UIModuleUITEDocument.UIStatusComboBox;
// Select 'Authorised' in 'Status' combo box
uIStatusComboBox.SelectedItem = this.SelectStatus_SPParams.UIStatusComboBoxSelectedItem;
}
The test method is able to change the value in the combobox, and an alert message is displayed to the user. However this part of the code uIStatusComboBox.SelectedItem = this.SelectStatus_SPParams.UIStatusComboBoxSelectedItem;
never returns and the test just hangs there until it timeouts!
I have no ideia how to work arround this issue! I was thinking that maybe the problem could be in the fact that we have javascript code that is executed after the alert is displayed to the user. I changed the JS so that the alert message is the last thing to be displayed but it also didn´t help!
I also noticed that if I click Ok on the alert message the test Pass!
If I select other value that dont trigger any JS the test also Pass!
Does anyone have any idea about this issue?
Edit 1:
I noticed another thing, I can use the BrowserWindow object to send a JS script to the browser. If I try to create an alert message the call also gets blocked until I click on the Ok button, on the alert!
BrowserWindow bw = BrowserWindow.Locate("My window");
bw.ExecuteScript("alert('This is just a simple alert.');");
The ExecuteScript statement also gets blocked until I click on the OK button!
This seems very very strange!
I believe I have found a workaround.
I was googling to find anything that could help me with this issue and I end up finding this question on StackOverflow Coded ui test - Select an item from a combobox without using mouse coordinates
I try to select the same item in the Dropdown without using the "SelectedItem" property of the HtmlComboBox element.
I try to use the keyboard to select the element in the dropdown box, first I click on the Dropdown and then I use the Down key and Enter key to select the element that I want:
public void SelectStatus_SP(string SelectedItem)
{
#region Variable Declarations
HtmlComboBox uIStatusComboBox = this.UIHttpsappWindow200.UIpopupUITEDocument5.UIWorkplaceDashboardsFrame.UIpopupUITEDocument.UIStatusComboBox;
#endregion
Mouse.Click(uIStatusComboBox);
Keyboard.SendKeys(uIStatusComboBox, "{Down}{Down}{Enter}", ModifierKeys.None);
}
In my case the element that I want to select is the 3rd one, so I go down 2 times and then hit enter on the element I want to select.
This workaround is not so good because if the element changes position I will select the worng one! But this was the only way I got for the test not to be stock in that part!
I wonder if anyone had a similar issue. Because to me this seems like a bug in the Coded UI Test engine, It doesn´t make any scence for the test to be stocked while the alert is not closed!

How go from one UI to another UI on Image button click event in juce introjucer?

can you please tell me How go from one UI to another UI on Image button click event in juce introjucer?
Basically you have to:
1.- Parent component must inherit from ButtonListener, and you must implement the buttonclicked method
void WindowComponent::buttonClicked (Button* activeButton)
{
if (activeButton == &someButton)
{
gotoOtherPage();
}
}
2.- Your "UIs" i must suppose are components, if so just do something like:
component.setVisible(false),
otherComponent.setVisible(true),
Or perhaps stash them in a TabbedComponent, hide the tabs or overlap some buttons and then just do:
tabbedComponent.setCurrentTabIndex(someIndex);
That should get you going, in case you need help to draw a button just do something like:
addAndMakeVisible (&someButton);
someButton.setBounds(...);
someButton.addListener(this);
Check out the doxygen docs, they are quite helpful.

Google Chrome Extension - How can I include a content script more than once?

I've been working on Chrome Extension for a website for the past couple of days. It's coming along really nicely but I've encountered a problem that you might be able to help with.
Here's an outline of what the extension does (this functionality is complete):
A user can enter their username and password into the extensions popup - and verify their user account for the particular website
When a user browses http://twitter.com a content script is dynamically included that manipulates the DOM to include an extra button next to each tweet displayed.
When a user clicks this button they are presented with a dialog box
I've made a lot of progress but here is my problem:
When a user visits Twitter the content script is activated and all tweets on the page get my new button - but if the user then clicks 'More...' and dynamically loads the next 20 tweets... these new additions to the page DOM do not get affected by the content script (because it is already loaded).
I could add an event listener to the 'More...' button so it then triggers the original content script again (and adds the new button) but i would have to predict the length of twitter's ajax request response.
I can't tap into their Ajax request that pulls in more tweets and call my addCurateButton() function once the request is complete.
What do you think is the best solution? (if there is one)
What you want to do is to re-execute your content-script every time the DOM is changed. Luckily there is an event for that. Have a look at the mutation event called DOMNodeInserted.
Rewrite your content script so that it attaches an event listener to the body of the DOM for the DOMNodeInserted event. See the example below:
var isActive = false;
/* Your function that injects your buttons */
var inject = function() {
if (isActive) {
console.log('INFO: Injection already active');
return;
}
try {
isActive = true;
//inject your buttons here
//for the sake of the example I just put an alert here.
alert("Hello. The DOM just changed.");
} catch(e) {
console.error("ERROR: " + e.toString());
} finally {
isActive = false;
}
};
document.body.addEventListener("DOMNodeInserted", inject, false);
The last line will add the event listener. When a page loads the event is triggered quite often so you should define a boolean (e.g. var isActive), that you initialize to false. Whenever the inject function is run check whether isActive == true and then abort the injection to not execute it too often at the same time.
Interacting with Ajax is probably the hardest thing to coax a content script to do, but I think you’re on the right track. There are a couple different approaches I’ve taken to solving this problem. In your case, though, I think a combination of the two approaches (which I’ll explain last) would be best.
Attach event listeners to the DOM to detect relevant changes. This solution is what you’ve suggested and introduces the race condition.
Continuously inspect the DOM for changes from inside a loop (preferably one executed with setInterval). This solution would be effective, but relatively inefficient.
The best-of-both-worlds approach would be to initiate the inspection loop only after the more button is pressed. This solution would both avoid the timing issue and be efficient.
You can attach an event-handler on the button, or link that is used for fetching more results. Then attach a function to it such that whenever the button is clicked, your extension removes all the buttons from DOM and starts over inserting them, or check weather your button exists in that particular class of DOM element or not and attach a button if it doesn't.

Resources