iPhone, Monotouch, and XIB outlet issues - c#

I'm having a problem with mapping controls in a subview back to fields on the owning controller. Specifically, I have mapped outlets for each of my "controls" to File's Owner. Monotouch then generated code for the controller's xib designer.cs file to reference these controls as properties on the controller class. However, when I run my code; I get object is null errors when trying to set properties on the controls. Digging into the issue with the debugger; it appears GetNativeField is returning null when trying to access the outlets by their names from the xib file.
Anyone have any ideas why this would be happening? I've checked the .xib file, and the generated code; the Outlet, Property, and Field names are consistent with one another.

Note that the outlets will only be accessible after the view has been loaded and that happens in LoadView() or by accessing the UIViewController's "View" property (this will load the view implicitly).
Only then the the IB content gets constructed and is available for use.
So if you want to change stuff, you would either manually call LoadView(), or override it in your view, call base.LoadView() and then access the outlets.

I figured out what was causing the issue; it was how I was pushing the controller on the stack:
using(var batteryController = new BatteryController()){
navigationController.PushViewController(batteryController,true);
}
It seems that when dispose is called on the controller, the NIB resource is removed from memory; which was causing the issue.
However, this brings up another question. Aren't you supposed to call dispose on the new controller once it's been pushed onto the stack? In objective C, when you push a controller on the stack; your supposed to call release afterwards. So what am I doing wrong then?

you should add the outlets on the AppDelegate. give this a try also on my blog it's a video of a simple calculator, it's in spanish but if you watch it its very self explanatory you can watch it here http://alexsoto.me/calculadora-monotouch it should help you to get started :) hope this helps Good luck, if i can help you on anything else just let me know
Edit: also you can check this video this one uses subviews also should help you, this one its in english http://www.alexyork.net/blog/post/Selecting-a-contact-from-the-Address-Book-with-MonoTouch.aspx

Related

Overriding the PageModel() constructer for setting up default properties (Razor Pages)

I am new to Razor Pages and looking for the best way to solve my problem.
Say I have an IndexModel class, that has some properties that rely on a DB context that is injected via the Constructer, such as a drop down list of Membership Levels, that comes directly from a table...
My question is what is the best way to handle populating this drop down list that I have for ALL requests that results in the same page being reloaded / returned. I know that I can put logic in OnGet to set up the list, the problem arises if say in OnPost, ModelState.IsValid is false, and so the page is returned with Page(). If I don't explicitly reinitialize the select list in OnPost, then I get a null reference exception, which is fair enough. Rewriting the code in the OnPost method goes against DRY principles, so I looked to writing a ConfirgureProperties() method in the class when needed.
Then by testing, I found that I can just set up a constructer that will take care of populating properties for me whenever they are needed, and I don't have to call anything else. Even when DI is involved, the injection is resolved at the top of the constructer, then I can use the context to do what I need for the other properties later in the constructer. I have seen no examples of this anywhere online, I only ever see people using constructers in page models that handle DI EXCLUSIVELY.
Is there a reason I SHOULD NOT be doing this, like bad coding practice or something, or is it ok for me to use page model constructers in this way?
Thanks
You only need to make the database call to repopulate the options in OnPost if ModelState is invalid. Chances are, if you have set up your validation correctly, that 99% of the time validation errors will be caught on the client and you won't need to repopulate the options.
Obtaining data from a database is costly, and you should only do it when necessary. So using the constructor approach contravenes this principal.
It's not like you are saving a lot of code either. Your ConfigureProperties method will only be called in two places in the PageModel.

Link Xamarin properties from different ViewModels

Is it possible to just "link" two properties of different ViewModels in a way such that when one property changes, the other one changes too. So in essence, I want two properties in different ViewModels behave as if they were one.
It would be nice if I could just do something like the following in my ViewModels:
WhenPropertyChanges(() => SettingX).CopyValueTo(() => ModelView2.SettingX);
Example: On my settings page, when I change a setting, I want the new value to be available in the ViewModel of another page.
I know I can achieve that with the third Layer (Model), but it feels a bit clunky and the way I solved it for now doesn't feel right (Firing events).
I've implemented following MVVM-Pattern from this page: http://www.wintellect.com/devcenter/krome/linking-property-change-notifications-in-xamarin-forms-or-wpfsilverlight. As far as I understood, the author says his code makes it possible, but unfortunately he doesn't show how.
I also found this article (http://blog.alectucker.com/post/2014/07/26/using-messageingcenter-in-xamarin-forms-for-viewmodel-to-viewmodel-navigation.aspx), but I don't necessarily want to navigate to the other View. Still, maybe I can use this MessagingCenter somehow to achieve my goal?
This is addressed in the final paragraph of my article that you reference. I use a simple extension method to do it. An example of this can be seen in the source code example from the article, in this file: https://github.com/Wintellect/XamarinSamples/blob/master/PropertyDependencyDemo%2FPropertyDependencyDemo%2FMvvm%2FObservableExtensions.cs
For your specific example, it would look something like this:
// using PropertyDependencyDemo.Mvvm;
// ... use the namespace above that contains the ObservableExtensions class
ModelView1
.WhenPropertyChanges((a) => a.SettingX)
.AlsoInvokeAction(() => ModelView2.SettingX = ModelView1.SettingX);
All this does is hook into the PropertyChanged event of the source viewmodel for you in a name-safe way.
One word of caution though: you need to be careful to not create a situation where you inadvertently prevent an object from being garbage collected. The reason this can happen is that in this example, ViewModel1 will now have a PropertyChanged handler that references a PropertyDependency object that in turn references both ModelView1 and ModelView2 due to the captured references in the Action lambda expression.
IF you know for sure that this won't be a problem (perhaps both go out of scope together), then there is nothing to worry about. But if you find yourself facing a situation where you need to prevent ModelView1 from keeping ModelView2 pinned, then you can do so using a WeakReference. Again, this is unlikely to be a concern, but if you find it leaking memory then you can change the above to this:
// assuming "TModelView" is the class name of the viewmodels
var wr = new WeakReference<TModelView>(ModelView2);
ModelView1
.WhenPropertyChanges((a) => a.SettingX)
.AlsoInvokeAction(() => {
TModelView mv;
if (wr.TryGetTarget(out mv))
mv.SettingX = ModelView1.SettingX;
});
I think if the navigation is lineare ( you only need the information of page 1 in page 2 ) you can use the MessagingCenter to do what you want.
If the user is able to change the data in the page 2 ( and be updated in the page 1 ) the messagingCenter is a little to tricky to use. I think you can use the first link you provide. Just use an abstract class with all shared data in your ViewModels.
If you want more help put an more completed code example.

HttpPostedFileBase is 0 bytes on POST for only the base view model property

I have this properly posting the image and binding to the HttpPostedFileBase property on my view model, but when I put the same property in the view model's base class, it doesn't model bind the bytes. It still shows the image name, but not the content stream.
I have tested everything I can think of. Please help!
These pictures tell the whole story:
Thanks in advance. Let me know if anything isn't clear.
UPDATE
I think this is a legit bug. I tried all the below suggestions (as of 1/26) before posting on SO. I also tried:
1. creating the base property as virtual and overriding it in the child class
2. creating a new property in the child class which merely gets/sets the base property
My solution, which is far from elegant, is to add a "temporary" property on the child class and first-thing in the MVC action method set the base property to it. I'm hoping a real solution presents itself and I can revert this cloodge and do the proper fix.
If it was me, I'd create a v.simple custom binder for the model class and hand crank it. Probably be easier to do that (and more obvious for future maintenance) than try to unpick the foibles of the DefaultModelBinder. Further, that would mean you wouldn't have to (unnecessarily) pollute your model structure /controller actions / unit tests.
Here's a good article on how to create a binder based on the default model binder: http://www.codeproject.com/Articles/605595/ASP-NET-MVC-Custom-Model-Binder.
HTH

Replace ListPickerPage with custom Page

I added the Windows Phone Toolkit with Nuget into my project.
Now I want to replace the default ListPickerPage with a custom page like this can be achieved for the DatePickerPage. (http://blogs.msdn.com/b/delay/archive/2010/09/21/there-are-lots-of-ways-to-ask-for-a-date-creating-custom-datepicker-timepicker-experiences-is-easy-with-the-windows-phone-toolkit.aspx)
Unfortunately this page does not provide an interface from which I could inherit.
The ListPicker.cs seems to have the reference hard coded:
private ListPickerPage _listPickerPage;
Even though it supports the PickerPageUri property.
I copied the ListPickerPage.xaml and code behind from the Source Repository and provided the path to this page as PickerPageUri.
The Page is opened but contains no content!
I think the reason is this part of code in the ListPicker.cs:
_listPickerPage = e.Content as ListPickerPage;
My class is not a "ListPickerPage" and therefore the reference remains null and no values will be set.
Next step I tried was to inherit from ListPickerPage to get the cast done.
Problem here: the public properties Items and some others have "private set" properties.
At the end, I always ended up with an empty target page.
Google + StackOverflow stated many times that one has to copy the page and simply refer to it via PickerPageUri, but this alone seems not to work.
Has anybody managed to get an own ListPickerPage in his project?

Overriding the return View when it is a mobile site to use a different view

Would it be possible to override the call to:
return View()
To append the string "mobile_" to the name of the view file, in other words, instead of calling the view "index.aspx" use "mobile_index.aspx".
Somewhere else I guess in a before action fires event I will check if its a mobile application, set a flag. So if the flag is set, it should append "mobile_" to the view name.
And I want this done at the controller level and not have to do this for each action.
What you want to achieve has been implemented by Stackoverflow.
I was trying to do the same recently and I bumped into this article.
It's really interesting and goes on the same road you want to follow.
At the end I decided to implement for my implementation to go this way.
The linked duplicate question has a number of options for implementing automatic mobile device detection; Scott Hanselman's is MVC3-specific so I'd start there.
However, to implement your exact solution is also possible. Create your own base controller class and override the View() method to do what you want before calling into the base View. Then derive all your site controllers from that.
The source code for MVC3 is published my MS so you should be able to see exactly what the base View() uses to figure out the view name, and "fix" it to be mobile_whatever.

Categories