I am starting to implement MVVM in my application and got an issue of knowing when the user navigated to the view.
To navigate between views, I can just use the navigationService.Navigate(...);
How do I check when I navigated to the view?
May I use the event navigationService.Navigated?
Is there no other method I can use like OnNavigatedTo that the page itself provide?
XAML:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP71"
xmlns:toolkit="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone.Controls.Toolkit"
DataContext="{Binding titleSearchViewModel, Source={StaticResource Locator}}">
<i:Interaction.Triggers>
<i:EventTrigger>
<cmd:EventToCommand Command="{Binding PageLoaded, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
VM:
private RelayCommand _PageLoaded;
public RelayCommand PageLoaded
{
get
{
if (_PageLoaded == null)
{
_PageLoaded = new RelayCommand(
() => Loaded()
);
}
return _PageLoaded;
}
}
In case this question is still actual, i prefer this solution: http://www.geoffhudik.com/tech/2010/10/10/another-wp7-navigation-approach-with-mvvm.html
If to use it, it is possible to send recipient ViewModel's parameters from the sender ViewModel:
SendNavigationMessage(Settings.NAVIGATION_PRODUCTS_SUBCATEGORIES,
new Dictionary<string, object> { { "SelectedIndex", Int32.Parse(item.id) } });
And receiver should define in xaml:
NavigatedToCommand="{Binding RefreshCommand}"
And then in receiver ViewModel:
public ICommand RefreshCommand // Should be set as NavigatedToCommand="{Binding RefreshCommand}" in xaml
{
get { return new RelayCommand(Refresh); }
}
public void Refresh()
{
_dataService.GetList(SelectedIndex, DownloadedCallback); // So, this would be called automatically after navigating is complete. SelectedIndex is updated at this moment.
}
Thanks for the answers provided. Both were helpful over a period of time until I decided to create a custom implementation of the navigation service that has been created by a few people.
I then made a contribution to the Cimbalino toolkit to suggest this and it has been introduced a while back.
I my personal opinion, that solves my issue the best. Have a look at the navigation service in there. The Navigated event pretty much solves my issue I had.
https://github.com/Cimbalino/Cimbalino-Toolkit
It basically comes down to this (in your viewmodel):
_navigationService.Navigated += OnNavigated;
Related
I am using Kotlin's html library kotlinx.html for dynamic html building.
I want to create a button which triggers a function when clicked. This is my current code:
class TempStackOverflow(): Template<FlowContent> {
var counter: Int = 1
override fun FlowContent.apply() {
div {
button(type = ButtonType.button) {
onClick = "${clicked()}"
}
}
}
fun clicked() {
counter++
}
}
This results in the following source code:
<button type="button" onclick="kotlin.Unit">testkotlin.Unit</button>
Which gives this error when clicked (from Chrome developer console):
Uncaught ReferenceError: kotlin is not defined at HTMLButtonElement.onclick
I have tried several approves, and search for a solution - but could not find the proper documentation.
I am not a Kotlin expert, but it's perfectly possible to write event handlers using kotlinx. Rather than:
onClick = "${clicked()}"
have you tried using this?
onClickFunction = { clicked() }
If you really need a bit on Javascript here, you can type this:
unsafe {
+"<button onClick = console.log('!')>Test</button>"
}
Good for debugging and tests, but not very nice for production code.
Unfortunately, you're completely missing the point of the kotlinx.html library. It can only render HTML for you, it's not supposed to be dynamic kotlin->js bridge, like Vaadin or GWT. So, you just set result of clicked function converted to String to onClick button's property, which is effective kotlin.Unit, because kotlin.Unit is default return value of a function if you not specify another type directly.
fun clicked() {
counter++
}
is the same as
fun clicked():Unit {
counter++
}
and same as
fun clicked():Kotlin.Unit {
counter++
}
So, when you set "${clicked()}" to some property it actually exec function (your counter is incremented here) and return Koltin.Unit value, which is becomes "Kotlin.Unit" string when it rendered inside "${}" template
I was looking at the sample code for the tutorial at https://forge.autodesk.com/blog/custom-window-selection-forge-viewer-part-iii which is located at https://github.com/Autodesk-Forge/forge-rcdb.nodejs/blob/master/src/client/viewer.components/Viewer.Extensions.Dynamic/Viewing.Extension.SelectionWindow/Viewing.Extension.SelectionWindow.Tool.js as well as the documentation at https://developer.autodesk.com/en/docs/viewer/v2/reference/javascript/toolinterface/ --- Most of these functions are getting called properly in my tool such as handleSingleClick, handleMouseMove, handleKeyDown, and so on, but two of them are not getting hit -- handleButtonDown and handleButtonUp. I was using viewer version 3.3.x but I have updated to use 4.0.x thinking that that might help to resolve the problem, but the same issue occurs in both versions. Thanks for any help.
The following code block from theAutodesk.Viewing.ToolController#__invokeStack(), _toolStack stands for activated tools in the ToolController, the method stands for callback functions started with handle, i.e. handleSingleClick, handleMouseMove, handleKeyDown, handleButtonDown, handleButtonUp, etc.
for( var n = _toolStack.length; --n >= 0; )
{
var tool = _toolStack[n];
if( tool[method] && tool[method](arg1, arg2) )
{
return true;
}
}
Based on my experience, if there is a handle function such as handleButtonDown or handleButtonUp executed before your custom tools' and returned true, then your handles will never be called.
Fortunately, Forge Viewer (v3.2) starts invoking a priority mechanism for custom tools registered in ToolController. ToolController will use the priority number to sort the tools in it, and the priority number of each tool is 0 by default. You can override the priority to make your tools be hit before other tools like this way, to add a function getPriority() to return a number greater than 0:
this.getPriority = function() {
return 100;
};
I found out that when using ES6 and the class syntax, extending your tool from Autodesk.Viewing.ToolInterface will prevent the overrides to work properly, probably because it is not implemented using prototype in the viewer source code.
You can simply create a class and implement the methods that are of interest for your tool:
// KO: not working!
class MyTool extends Autodesk.Viewing.ToolInterface {
getName () {
return 'MyTool'
}
getNames () {
return ['MyTool']
}
handleButtonDown (event, button) {
return false
}
}
// OK
class MyTool {
getName () {
return 'MyTool'
}
getNames () {
return ['MyTool']
}
handleButtonDown (event, button) {
return false
}
}
I'm looking to hook-up sort events performed on ng2-smart-table. Followed https://akveo.github.io/ng2-smart-table/#/documentation, I see bunch of events that are exposed like rowSelect, mouseover etc but I don't see sort events published/emitted by the library. I'm thinking of changing Ng2SmartTableComponent and emit an event when (sort) is called internally. May I know if anyone did it already or is there a hack I can rely upon.
The source of the sort in ng2-smart-table is shown on GitHub (link to code).
If you want to change the compare-Function (as used by default) you can add your own custom function in your ng2-smart-table-configuration:
columns: {
group_name: {
title: 'Groupname',
compareFunction(direction: any, a: any, b: any) => {
//your code
}
}
}
I was searching for an event to sort my data remotely and I have found a solution. Also I have some logic for page change event (remote paging). Here is what works for me.
ts
source: LocalDataSource = new LocalDataSource();
ngOnInit() {
this.source.onChanged().subscribe((change) => {
if (change.action === 'sort') {
this.sortingChange(change.sort);
}
else if (change.action === 'page') {
this.pageChange(change.paging.page);
}
});
}
html
<ng2-smart-table [settings]="settings" [source]="source"></ng2-smart-table>
This solution won't replace custom logic but it might help you solve your problem.
I'm working with a wizard component. The navbar is in the botton but my boss wants me to put it in the top of the wizard,I thought that it was an attribute or tag to do it straight forward but I have been reviewing the documentation and I should be wrong (I only found the showNavBar tag).
Is there a way to do it without css or jquery? (we have some problems in the application setting css when working with some components so I would like to avoid it).
Thank you very much
You can achieve this in either of the two ways:
1 - Extending the WizardRenderer
By extending the WizradRenderer you can change the order of the encoding.
In the original Renderer the encodeContent(facesContext, wizard); is called before encodeNavigators(facesContext, wizard); so it's pretty much simple, extend you custom renderer, change the order of the calls.
public class ExNavWizardRenderer extends org.primefaces.component.wizard.WizardRenderer{
#Override
protected void encodeMarkup(FacesContext facesContext, Wizard wizard) throws IOException {
ResponseWriter writer = facesContext.getResponseWriter();
String clientId = wizard.getClientId(facesContext);
String styleClass = wizard.getStyleClass() == null ? "ui-wizard ui-widget" : "ui-wizard ui-widget " + wizard.getStyleClass();
writer.startElement("div", wizard);
writer.writeAttribute("id", clientId, "id");
writer.writeAttribute("class", styleClass, "styleClass");
if(wizard.getStyle() != null) {
writer.writeAttribute("style", wizard.getStyle(), "style");
}
if(wizard.isShowStepStatus()) {
encodeStepStatus(facesContext, wizard);
}
// encode the navigators before the content
if(wizard.isShowNavBar()) {
encodeNavigators(facesContext, wizard);
}
encodeContent(facesContext, wizard);
writer.endElement("div");
}
}
Update your faces-config.xml
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.WizardRenderer</renderer-type>
<renderer-class>com.projectPackage.ExNavWizardRenderer</renderer-class>
</renderer>
</render-kit>
2 - jQuery
In your document.ready you can change the DOM, for example this would do the same as the Renderer:
$('.ui-wizard-step-titles').after($('.ui-wizard-navbar'))
When I create plane java Swing components like dialog boxes etc, it is very easy to make a unit test to display the Dialog. Basically, I can just create an instance of the dialog and call setIsVisible(true). I'm having a really tough time figuring out how to do this with a griffon View. I've been trying to do this with integration tests but I can't seem to get it.
I've tried a few things to show the view and nothing seems to work. The only way I seem to be able to get an instance of the view is:
AirplaneView view = helper.newInstance(app, griffonpractice.AirplaneView.class, "Airplane")
After this I thought I may be able to do a view.setIsVisible(true) or view.frame.setIsVisible(true) but no luck. I'm guessing I am thinking about this the wrong way, there has to be a fairly simple way to do this. Any help is appreciated. My view looks like the following, note that there are no bindings so I shouldn't need to mock anything.
package griffonpractice
import javax.swing.JFrame
JFrame frame = application(title: 'GriffonPractice',
size: [320,480],
pack: true,
location: [50,50],
locationByPlatform:true){
borderLayout()
{
hbox(constraints: BL.NORTH)
{
label(text: "shane")
label(text: "Jack");
}
}
}
Have you tried using FEST? http://easytesting.org
The book Griffon in Action has a detailed example on testing a Griffon application using FEST, the source code is available at http://code.google.com/p/griffoninaction/source/browse/trunk/chap09/dictionary
Here's a short example of 3 tests for a simple application
package dictionary
import org.fest.swing.fixture.*
import griffon.fest.FestSwingTestCase
class DictionaryTests extends FestSwingTestCase {
void testInitialState() {
window.button('search').requireDisabled()
}
void testWordIsFound() {
window.with {
textBox('word').enterText('griffon')
button('search').click()
textBox('result')
.requireText('griffon: Grails inspired desktop application development platform.')
}
}
void testWordIsNotFound() {
window.with {
textBox('word').enterText('spock')
button('search').click()
textBox('result')
.requireText("spock: Word doesn't exist in dictionary")
}
}
protected void onTearDown() {
app.models.dictionary.with {
word = ""
result = ""
}
}
}