I have a list on my view model that contains an object and property that I am trying to bind to from the main view.
var field = new UITextField();
Add(field);
this.AddBindings(
new Dictionary<object, string>()
{
{ field, "Text Names[0].Value" }
}
);
This will load fine and display the initial value from the view model but won't receive any values back when UITextField.Text is modified. It seems like it is not 2 way. Value is not a notification property but could be made into one if that is what this setup requires.
I also tried the following but that does work at all:
set.Bind(field).To(vm => vm.Names[0].Value);
Using MvvmCross 3.0.9. Xamarin.iOS 6.3.7
I've just tested this using 3.0.9 with a ViewModel which has an ObservableCollection of non-INPC Thing objects and this two way binding seems to work OK for me - both when the ObservableCollection changes and when the UITextField value changes because of user action.
Can you provide any more of your ViewModel nad list object code? (If not, can you reproduce the error in a simple sample?)
Can you provide any error trace you are seeing (in debug|output)? (This may need enabling - see MvvmCross Mvx.Trace usage)
Can you provide any more information on the form that "does work at all" - this might be a clue about what is going wrong.
Related
I am currently working on a JSF 2.2 application. As per requirements, I have created custom view handler (using ViewHandlerWrapper) for my application. All the methods are just passing to default view handler except renderView which I am overriding as follows -
private viewHandler viewHandlerWrapped = null;
renderView(FacesContext facesContext, UIViewRoot viewToRender) {
String viewId = viewToRender.getViewId();
if (viewId == some condition) {
/* Do calculation to derive viewId */
}
UIViewRoot viewRoot = viewHandlerWrapped.createView(facesContext,viewId+"?faces-redirect=true");
facesContext.setViewRoot(viewRoot);
//now let system render the view
viewHandlerWrapped.renderView(facesContext,viewRoot);
}
The above is working fine and rendering & navigation is happening as expected. The only issue is faces-redirect=true is not working. The URL seems to be always one behind.
I have gone through many answers given in stackoverflow or internet. But nowhere I am able to find how to solve this.
I think I am doing something wrong e.g. ?faces-redirect=true might not be the correct way while creating view. But I am not sure what can be done to correct this.
Can someone please help me out with this?
After struggling with this for more than 4 weeks, I finally found a way to get the correct URL (instead of previous one). I am updating my answer here in case any one else falls into same problem -
"It looks like we can not use the faces-redirect=true the way I was using while creating and rendering the pages. It should be suffixed with form action. So I have changed my code as follows -
1) actions are returned on click of a button e.g.
public string doAction {
----
return "action?faces-redirect=true";
}
2) Code is updated to use implicit navigation wherever possible. With this, I didn't need to build my custom viewhandler as navigation is happening implicitly. So, I have scrapped the viewhandler.
With above two simple steps, the correct URL is being displayed on the browser now.
I'm attempting to create view/viewModel pair to act as a MessageBox replacement which will be called by the UIVisualizer Service. The viewModel has five different constructors, one being the default, and the others to define the different attributes of the MessageBox(e.g. Type, Image, Message, Title, etc.). I will be creating the viewModel using one of the four non-Default constructors each time I desire a MessageBox to popup. I am doing this versus using the built-in MessageService is because I'm using third party controls for my application and I want the MessageBox look-and-feel to match the rest of the application.
My problem is that even though I'm creating the viewModel, Catel is not using the viewModel I pass in to UIVisualizer, but is creating a new viewModel from the default constructor.
Does anybody know how to get this behavior to stop.
The best thing to do is create your own version of the IMessageService (create new class deriving from MessageService and override the Show method).
Catel should re-use the passed in view model. If you think you have found a bug, please report it at http://www.catelproject.com/support/issue-tracker
I have a nested control (NC1) which contains 3 instances of NC2. When the containing view is first opened, NC1 will be null and so the three instances of NC2 will be null. This appears to work correctly based on debugging through my code and the framework.
When a selection is made in the containing view NC1 is properly set (and the ViewModel is (re)created) and values for its properties (exposed through Fody.Expose) appear in the view. However, none of the ViewModels for NC2 are (re)created and they do not reflect the values provided by their respective models.
I am not sure exactly what information to provide without uploading a lot of content, so I will take a stab.
In the NC1 view, I have the following
<localViews:NC2 DataContext="NC2Entry1"/>
<localViews:NC2 DataContext="NC2Entry2"/>
<localViews:NC2 DataContext="NC2Entry3"/>
NC2EntryX are properties on the NC1 ViewModel that return a specific instance of an NC2 model from a list. The NC2EntryX properties is NOT registered with RegisterProperty.
As a note, I have discovered that I must have an empty parameter constructor for the NC1 and NC2 view models. If I do not, then I receive a MissingMethod exception when the view model is being created when the TypeFactory attempts to create the ViewModel with the Activator instead of using the injection path. The injection path is not used because the call at line 591 of TypeFactory returns false because the NC2 model passed is 'not registered'. (Not sure if it should be or how to make it so.)
I am using Catel version 3.9.0
The NC2EntryX property changes must be reflected to the view somehow. You can do this by making it Catel properties, or by calling RaisePropertyChanged("NC2EntryX") yourself when setting the property value. Only in that case the view will be updated (this is just standard WPF / MVVM behavior).
About the missing method exception: it is a first chance exception where the TypeFactory tries to fall back to Activator.CreateInstance when it fails to create the type with dependency injection. No need to worry about this. If you don't want view models to be alive without a model, don't create an empty constructor.
I'm trying to bind a UITableView to an ObservableCollection<MyTypeViewModel> using MvxStandardTableViewSource, and I'm getting weird behavior and bindings that aren't working
The (partial) code is this:
tblFeatures = new UITableView ();
mSource = new MvxStandardTableViewSource(tblFeatures, "TitleText Name");
var set = this.CreateBindingSet<MyTypeView, MyTypeViewModel> ();
set.Bind(mSource).To (vm => vm.Objects);
set.Bind(mSource).For(s => s.SelectedItem).To (vm => vm.SelectedObject);
set.Apply ();
What I'm seeing is that when I select an item in the table, it does update SelectedObject with the new value. But when I change SelectedObject by some other means, the table does not update the displayed selected item. I have verified that the SelectedObject really is being changed, by setting a breakpoint and by binding another control to it; the other control (a label) does change as the selection changes, but the UITableView does not.
Am I doing something wrong, or could this be an issue in MVVMCross?
The selecteditem binding was requested as a 'nice to have' and was mainly requested for the user story where a user clicks on a list item - so this is currently a 'one way to source' implementation.
The very basic details and some code can be found via - https://github.com/slodge/MvvmCross/issues/278
In truth, the current binding is abusing the 'selected' paradigm - as it doesn't really reflect the selection state of the cell and also has no handling of mutiselect - instead it just lets the viewmodel know the latest tapped item.
If there are genuine user stories/requirements for full two'way binding, then these should be addable - eg if the user story were for scrolling the item into view then 'scrollToRowAt' could be used - see How to scroll UITableView to specific position - but this again might not be true 'selection' within the uitableview.
if you wanted to implement this yourself it should be fairly straight-forward to override the binding with your own one (see the custom binding n+1 in http://mvvmcross.wordpress.com for an intro on custom bindings).
could this be an issue in MVVMCross?
Overall I think I'd categorise it as a known limitation of that particular binding caused by lack of user demand and by some confusion over whether selection genuinely means selection in the touch screen era.
if it was logged as a bug I'd say it wasn't.. If it was logged ss a feature request I'd try getting as much user input as i could about what devs really want from this, whether they want true cell selection or scroll into view, both or something more.
By other means you mean not from UI thread I presume. Please try by invoking the change on UI thread.
I have a MainView which has an associated MainViewModel in my WPF application, assigned via its contructor.
App > start up uri > MainWindow.xaml
public MainWindow()
{
InitializeComponent();
var viewModel = new MainViewModel();
DataContext = viewModel;
}
My MainView holds as many as four nested views or child views who are hidden and displayed based upon the button that has been clicked on the MainView. So we toggling the visibility property vi a binding which gets updated via command bindings assigned to each button on the MainView.
Each nested View does not have an associated ViewModel, all bindings found on child views find their information in the MainViewModel. So binding system ends waling up the UI tree of the app to find out that the parent 'MainView' has an associated ViewModel.
So overall there is 'ONE' -> ViewModel. This seems to work fine and but as expected this VM has gotten to big and needs re-factoring. It holds information that contextually it should not. But this is a proof concept application. So i decided to keep it simple and make sure it was do-able.
PROBLEM:
When i tried assigning a empty view with an empty view model I noticed binding errors in the output window and as expected weird and broken behaviour. Which makes no sense ... Is there a more clear and concise way of letting WPF know how to handle any bindings it finds in a nested view control? I thought if each view's constructor assigned itself a corresponding VM as shown above, then it should work as this logically makes sense. Unfortunately all buttons on the MainView stop working when the corresponding view it is designated to switch on and hide the others has an associated ViewModel. On some buttons it works and the others it does not? This is really weird?
As mentioned in my answer above, the problem was that WPF binding system was struggling to to resolve bindings at run time. The main view has its associated view model instantiated and assigned via the Main View contructor and this pattern is repeated for all nested views that the MainView also houses.
By default, I tend to use the implied binding syntax which means that without explicitly specifiying a source the binding system will try to resolve the name you supply in the binding. So it's all implied and nothing is explicitly set!
Upgrading each nested view to have its own view model makes this auto discovery/resolution of bindings go a little crazy and I have not explicitly told the binding system where to find the property I am looking for hence the output window binding errors.
This leads to unexpected behaviour as the output window was telling that it was trying to resolve binding expressions in nested views --> viewmodels. When in actual fact that VM it is looking in, IS EMPTY!
So clearly the binding system is good when you do not explicitly set a source property inside the binding syntax. It is clever enough to find things on its own. In my case it needed some extra help, as it was unsure as to where to find things.
SOLUTION:
Remove the constructor declaration for the MainViewModel in the MainView constructor.
Scope in an xmlns for ViewModels namesapce into your MainView.xaml
Create a window resource inside the MainView .xaml
Give the resource a key.
Upgrade all your bindings in the MainView xaml file to include source property.
Give the source property a static resource binding that points to your ViewModel key value set up in step 4.
Only do step 6 for bindings who refer to the ViewModel that is associate with the MainView.
All nested views are to be left alone, they should handle their own bindingds in their own xaml files. The MainView simply instantiates them and places them onto the UI. For me this was the case, I did not have any more bindings concerning my nested views. All Bindings that lived on the MainView.xaml file referred to data in the MainViewModel.cs. This makes alot easier when viewing your problem.
For some reason the editor was being awkward so I chose to omit any sample code but the steps above are descriptive enough to follow the steps that I took. Above is what worked for me.
ANOTHER WAY OF SUMMING UP THIS PROBLEM
Most books teach the shorter binding syntax
What happens when more than one data context is available?
How is the binding system supposed to know how to resolve your short hand binding expressions.