Bing Maps MVVM in universal app - mvvm

For a long time i´ve been trying to understand the correct way of dealing with bing Maps in n MVVM scenario.
I might create a map in my XAML-view like this:
<map:Map x:Name="MyMap"
Credentials="MySuperSecretCredentials"/>
I the code behind file I can easily interact with map for eaxmple like this:
private async void FindMe_Clicked()
{
_cts = new CancellationTokenSource();
CancellationToken token = _cts.Token;
// Get the location.
Geoposition pos = await _geolocator.GetGeopositionAsync().AsTask(token);
MyMap.SetView(new BasicGeoposition() { Latitude = pos.Coordinate.Latitude, Longitude = pos.Coordinate.Longitude }, 15);
}
Simply by referencing the MyMap we can do whatever we like with it in the code behind.
But how can I execute the same command my viewModel?
I guess I should start with replacing the FindMe_Clicked with a command calling a method on my viewModel? And have that method execute a method similar to the one in the code-behind. But How do I acess MyMap in the viewModel?
Maybe my VM looks like this:
public class MainViewModel
{
public RelayCommand GetLocation { get; private set; }
public MainViewModel()
{
this.GetLocation = new RelayCommand(this.FindMe());
}
public void FindMe()
{
_cts = new CancellationTokenSource();
CancellationToken token = _cts.Token;
// Get the location.
Geoposition pos = await _geolocator.GetGeopositionAsync().AsTask(token);
MyMap.SetView(new BasicGeoposition() { Latitude = pos.Coordinate.Latitude, Longitude = pos.Coordinate.Longitude }, 15);
}
}
If im not thinking about this problem all wrong what I need to do Is to pass the same instance of MyMap that exists in the view to my viewmodel somehow?
Help with this is appreciated, I would also love to see any examples of how to use bibg maps i portable class libraries or i an Mvvm-pattern if anyone has come across it somewhere. Thanks!

When following the MVVM pattern, you should never try to access elements of the View layer (e.g. the maps control) from within the Viewmodel. Instead, you'd (theoretically) create two public properties CenterLatitude and CenterLongitude and bind them to the maps control directly within XAML code:
<Map Credentials="MySuperSecretCredentials" ZoomLevel="15">
<Map.Center>
<Location Latitude="{Binding CenterLatitude}" Longitude="{Binding CenterLongitude}"/>
</Map.Center>
</Map>
It's ok to have a method FindMe within your Viewmodel, but instead of accessing the MyMapcontrol and calling SetView(...) from within there, you'd just update the two properties CenterLatitude and CenterLongitude and make sure that the PropertyChanged event is raised in order to inform the View about the changed data and to update itself.
BUT: Unfortunately, the bing map control's Center attribute does not support Data Binding - it seems that Microsoft turned this feature off intentionally for performance reasons. If you still want to keep the MVVM pattern, check out this article I've written some time ago that explains how to circumvent this restiction.
(In my experience, this workaround works quite well and does not affect performance. Just make sure that you don't update the Center property too often, meaning several times per second...)

Related

freshmvvm access PageModel from Page code behind

Im using xamarin forms with freshmvvm framework.
I would like to know how I can skip using xaml, and just access binding data from code behind in c#.
Are there any code samples that could help?
Although this goes against the principles of MVVM there is of course a way to do it.
Without a MVVM framework you would just create a ViewModel by hand and set the BindingContext (documentation) yourself. The 'only' thing (in regard to this) a MVVM framework does for you is set that binding up automatically so you're not bothered with writing the same code over and over again.
So, imagine you have this ViewModel, note I user PageModel to match the FreshMvvm naming:
// SamplePageModel.cs
public class SamplePageModel
{
public string Foo { get; set; } = "Bar";
}
Now in my Page, I set the BindingContext like this:
// SamplePage.cs
// ... Skipped code, just constructor here:
public SamplePage()
{
InitializeComponent();
BindingContext = new SamplePageModel();
}
Now you can bind to any property of SamplePageModel.
FreshMvvm does this part automagically.
If, for whatever reason, you would like to access the ViewModel/PageModel directly, just do the reverse. Somewhere in your Page or code-behind you can do:
// ... Some code here
var pageModel = BindingContext as SamplePageModel;
// ... More code here
Now if pageModel isn't null there you have your data-bound and filled PageModel!
I found Gerald's answer helpful, but I found that you need to override this event in your page vs doing the as in the constructor:
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
var pageModel = BindingContext as YourFreshMVVMPageModel;
// Modify the page based on the pageModel
}
The PageModel construction seems to take place after the page Constructor, and this Event seems to fire at the right time and still make the page do what you want.

Does anyone know a good example of ReactiveCommand for ReactiveUI?

I'm inexperienced, especially at MVVM, but trying to use ReactiveUI, and I'm not understanding the examples that I'm finding that demonstrate ReactiveCommand. I have used ICommand / DelegateCommand one time before, but this is different, and I'm not getting it.
What I'm trying to do is really simple. Click a button in the view, and have that execute a method in the view model. The examples that I'm finding all involve IObservable<>, and I don't get that, as they don't explanations that are geared to the total noob that I am.
Basically, I'm trying to use this as a learning experience, and what I'd ideally like to do is bind the button's Command property in xaml to a command (however that works, I don't know), which causes a method to execute. No collections, I'd just be passing a single int variable.
Thanks for the help. I really appreciate it.
Edit - Below appears code using Paul Betts' suggestions:
C#
public ReactiveCommand AddToDailyUsed { get; protected set; }
public MainPageVM()
{
Initialize();
AddToDailyUsed = new ReactiveCommand();
AddToDailyUsed.Subscribe(AddToTodayUsedAction => this.AddToDailyUsedExecuted());
}
private object AddToDailyUsedExecuted()
{
MessageBox.Show("AddToDailyUsedAction");
return null;
}
private void AddToDailyUsedAction(object obj)
{
MessageBox.Show("AddToDailyUsedAction");
}
XAML
<Button Content="{Binding Strings.add, Source={StaticResource LocalStrings}}"
Command="{Binding AddToTodayUsed}"
Margin="-5,-10, -10,-10"
Grid.Row="3"
Grid.Column="2" />
Obviously I'm missing something. I inserted break points at the AddToDailyUsedExecuted and AddToDailyUsedAction methods, and they are never reached.
Edit Constructor for code behind the view:
MainPageVM mainPageVM = new MainPageVM();
public MainPage()
{
InitializeComponent();
Speech.Initialize();
DataContext = mainPageVM;
ApplicationBar = new ApplicationBar();
TaskRegistration.RegisterScheduledTask();
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
//Shows the rate reminder message, according to the settings of the RateReminder.
(App.Current as App).rateReminder.Notify();
}
So, ReactiveCommand is itself an IObservable<object> - in this case, you can conceptualize IObservable as an Event - this Event fires when the command is invoked (i.e. when the button is pressed). So, in your constructor, you might write:
MyCommand = new ReactiveCommand();
MyCommand.Subscribe(param => this.MyCommandHasExecuted());
However, what's neat about IObservable that isn't true about regular events, is that you can use LINQ on them:
// Now, MyCommandHasExecuted only gets run when the UserName isn't null
MyCommand.Where(param => this.UserName != null)
.Subscribe(param => this.MyCommandHasExecuted());
Update: Your Xaml binds to AddToTodayUsed but your ViewModel command is called AddToDailyUsed. Could that be it?

Unit testing with EF Code First DataContext

This is more a solution / work around than an actual question. I'm posting it here since I couldn't find this solution on stack overflow or indeed after a lot of Googling.
The Problem:
I have an MVC 3 webapp using EF 4 code first that I want to write unit tests for. I'm also using NCrunch to run the unit tests on the fly as I code, so I'd like to avoid backing onto an actual database here.
Other Solutions:
IDataContext
I've found this the most accepted way to create an in memory datacontext. It effectively involves writing an interface IMyDataContext for your MyDataContext and then using the interface in all your controllers. An example of doing this is here.
This is the route I went with initially and I even went as far as writing a T4 template to extract IMyDataContext from MyDataContext since I don't like having to maintain duplicate dependent code.
However I quickly discovered that some Linq statements fail in production when using IMyDataContext instead of MyDataContext. Specifically queries like this throw a NotSupportedException
var siteList = from iSite in MyDataContext.Sites
let iMaxPageImpression = (from iPage in MyDataContext.Pages where iSite.SiteId == iPage.SiteId select iPage.AvgMonthlyImpressions).Max()
select new { Site = iSite, MaxImpressions = iMaxPageImpression };
My Solution
This was actually quite simple. I simply created a MyInMemoryDataContext subclass to MyDataContext and overrode all the IDbSet<..> properties as below:
public class InMemoryDataContext : MyDataContext, IObjectContextAdapter
{
/// <summary>Whether SaveChanges() was called on the DataContext</summary>
public bool SaveChangesWasCalled { get; private set; }
public InMemoryDataContext()
{
InitializeDataContextProperties();
SaveChangesWasCalled = false;
}
/// <summary>
/// Initialize all MyDataContext properties with appropriate container types
/// </summary>
private void InitializeDataContextProperties()
{
Type myType = GetType().BaseType; // We have to do this since private Property.Set methods are not accessible through GetType()
// ** Initialize all IDbSet<T> properties with CollectionDbSet<T> instances
var DbSets = myType.GetProperties().Where(x => x.PropertyType.IsGenericType && x.PropertyType.GetGenericTypeDefinition() == typeof(IDbSet<>)).ToList();
foreach (var iDbSetProperty in DbSets)
{
var concreteCollectionType = typeof(CollectionDbSet<>).MakeGenericType(iDbSetProperty.PropertyType.GetGenericArguments());
var collectionInstance = Activator.CreateInstance(concreteCollectionType);
iDbSetProperty.SetValue(this, collectionInstance,null);
}
}
ObjectContext IObjectContextAdapter.ObjectContext
{
get { return null; }
}
public override int SaveChanges()
{
SaveChangesWasCalled = true;
return -1;
}
}
In this case my CollectionDbSet<> is a slightly modified version of FakeDbSet<> here (which simply implements IDbSet with an underlying ObservableCollection and ObservableCollection.AsQueryable()).
This solution works nicely with all my unit tests and specifically with NCrunch running these tests on the fly.
Full Integration Tests
These Unit tests test all the business logic but one major downside is that none of your LINQ statements are guaranteed to work with your actual MyDataContext. This is because testing against an in memory data context means you're replacing the Linq-To-Entity provider but a Linq-To-Objects provider (as pointed out very well in the answer to this SO question).
To fix this I use Ninject within my unit tests and setup InMemoryDataContext to bind instead of MyDataContext within my unit tests. You can then use Ninject to bind to an actual MyDataContext when running the integration tests (via a setting in the app.config).
if(Global.RunIntegrationTest)
DependencyInjector.Bind<MyDataContext>().To<MyDataContext>().InSingletonScope();
else
DependencyInjector.Bind<MyDataContext>().To<InMemoryDataContext>().InSingletonScope();
Let me know if you have any feedback on this however, there are always improvements to be made.
As per my comment in the question, this was more to help others searching for this problem on SO. But as pointed out in the comments underneath the question there are quite a few other design approaches that would fix this problem.

Can execute question using delegate commands in prism

This seems like a dumb question but I have looked through the docs for prism and searched the internet and can't find an example... Here is the deal.
I am using a DelegateCommand in Prism, it is working fine except when I assign a delegate to the can execute to the CanExecute method. in another view model I have a event that takes a bool that I am publishing too and I can see that the event is firing and that the bool is getting passed to my view model with the command in it no problem but this is what I don't understand... How does can execute know that the state has changed? Here is some code for the example.
from the view models ctor
eventAggregator.GetEvent<NavigationEnabledEvent>().Subscribe(OnNavigationEnabledChange, ThreadOption.UIThread);
NavigateCommand = new DelegateCommand(OnNavigate, () => nextButtonEnabled);
Now - here is the OnNavigationEnableChange event.
private void OnNavigationEnabledChange(bool navigationState)
{
nextButtonEnabled = navigationState;
}
enter code here
Like - I am totally missing something here - how does the command know that nextButtonEnabled is no true?
If someone could point me to a working example that would be awesome.
OK - thanks!
This is why I don't use the implementation of DelegateCommand in Prism. I've always hated the callback-based approach for enabling/disabling commands. It's entirely unnecessary, and as far as I can tell, its only (and rather doubtful) 'benefit' is that it's consistent with how execution itself is handled. But that has always seemed pointless to me because execution and enabling/disabling are clearly very different: a button knows when it wants to execute a command but doesn't know when the command's status might have changed.
So I always end up writing something like this:
public class RelayCommand : ICommand
{
private bool _isEnabled;
private Action _onExecute;
public RelayCommand(Action executeHandler)
{
_isEnabled = true;
_onExecute = executeHandler;
}
public bool IsEnabled
{
get { return _isEnabled; }
set
{
_isEnabled = value;
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
public bool CanExecute(object parameter)
{
return _isEnabled;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_onExecute();
}
}
(If necessary you could modify this to use weak references to execute change event handlers, like Prism does.)
But to answer your question: how is the callback approach even meant to work? Prism's DelegateCommand offers a RaiseCanExecuteChanged method you can invoke to ask it to raise the event that'll cause command invokers to query your command's CanExecute. Given that you have to tell the DelegateCommand any time your enabled status changes, I don't see any meaningful benefit of a callback-based approach. (Sometimes you see a broadcast model though - arranging so that any change in status anywhere notifies all command invokers! In that case, a callback is useful because it means it doesn't matter if you don't know what actually changed. But requerying every single command seems unpleasant to me.)
Answering your question how does the command know that it is now enabled:
NavigateCommand = new DelegateCommand(OnNavigate, () => nextButtonEnabled);
This overload of the DelegateCommand constructor takes 2 parameters:
The first is the command action and the second is the CanExecute delegate that returns bool.
in your example your CanExecute action always returns nextButtonEnabled
eventAggregator.GetEvent<NavigationEnabledEvent>().Subscribe(OnNavigationEnabledChange, ThreadOption.UIThread);
triggers OnNavigationEnabledChange that changes nextButtonEnabled
this is how it works...

Silverlight MVVM header detail

So lets say i have an OrderModel and an OrderViewModel. I have the Supplier, Order Date, etc properties on both the ViewModel and the Model and they are linked up. Seen examples on this and seems straighforward enough, although somewhat duplicated in terms of writing setters/getters.
Now what do I do with the OrderDetails? In my model I would have a List.
Do I have an OrderDetailViewModel for the OrderDetail? If so then how does the OrderViewModel provide that? As an ObservableCollection? And if so how do you keep that in sync with the original List?
This is where I haven't seen a decent example. If there is one out there someone could point me to, I'd appreciate it. I liek the concept of the MVVM but I am starting to thing its a hell of a lot of overhead. Why not just have the ViewModel handle the model part as well. In day to day LOB apps is there really that much difference between the two to warrant all the code that true MVVM seems to required?
It looks like this is what you need: http://jonas.follesoe.no/SpeakingAtMSDNLiveNextMonth.aspx
A translation on google gives this as the abstract for the talk:
Silverlight 2 was released this autumn, and lays a good foundation for developers who want to create rich Internet applications (RIA) based on. NET. In this session we in Depth in Silverlight 2 that development and the benefits of choosing Silverlight 2 as a platform for data-centric business applications. The session will cover among other things, data access via secured WCF services, how to structure the code using the Model-View-View Model pattern (MVVM), how to write code, designers can work with, and easy-Blend tips for developers. The session will be built around a dive log application where the code will be available after the presentation.
However in the mean time Jonas has already talked about MVVM here:
http://jonas.follesoe.no/YouCardRevisitedImplementingTheViewModelPattern.aspx
You can use something like this to keep your ObservableCollections synchronised between the model and view model:
/// <summary>
/// Keeps one collection synchronised with another.
/// </summary>
/// <typeparam name="Source">The type of the source items.</typeparam>
/// <typeparam name="Destination">The type of the destination items.</typeparam>
public class CollectionSync<Source, Destination>
{
private readonly Func<Source, Destination> _destItemFactory;
private readonly Action<Destination> _destItemRemover;
private readonly IList<Destination> _destList;
private readonly IList<Source> _sourceList;
/// <summary>
/// Initializes a new instance of the <see cref="CollectionSync<Source, Destination>"/> class.
/// </summary>
/// <param name="sourceList">The source list.</param>
/// <param name="destList">The destination list.</param>
/// <param name="destItemFactory">Factory method which creates a Destination for a given Source.</param>
/// <param name="destItemRemover">Method called when a Destination is removed.</param>
public CollectionSync(IList<Source> sourceList,
IList<Destination> destList,
Func<Source, Destination> destItemFactory,
Action<Destination> destItemRemover)
{
_destItemFactory = destItemFactory;
_destItemRemover = destItemRemover;
_sourceList = sourceList;
_destList = destList;
((INotifyCollectionChanged) _sourceList).CollectionChanged += SourceCollection_CollectionChanged;
PopulateWithAllItems();
}
private void PopulateWithAllItems()
{
foreach (Source sourceItem in _sourceList)
_destList.Add(_destItemFactory(sourceItem));
}
private void SourceCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
{
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
OnItemsAdded(args.NewStartingIndex, args.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
OnItemsRemoved(args.OldStartingIndex, args.OldItems);
break;
case NotifyCollectionChangedAction.Reset:
OnItemsReset();
break;
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
throw new NotImplementedException();
}
}
private void OnItemsReset()
{
_destList.Clear();
PopulateWithAllItems();
}
private void OnItemsRemoved(int index, ICollection items)
{
int itemCount = items.Count;
for (int i = 0; i < itemCount; i++)
{
Destination removed = _destList[index];
_destList.RemoveAt(index);
if (_destItemRemover != null)
_destItemRemover(removed);
}
}
private void OnItemsAdded(int index, IList items)
{
int itemIndex = index;
foreach (Source item in items)
{
// Add to Items collection
_destList.Insert(itemIndex, _destItemFactory(item));
itemIndex++;
}
}
}
Taking your Order/OrderDetails example, in your Order view model you would hook up the two ObservableCollections like this:
_modelToViewModelSync = new CollectionSync<IOrderDetail, OrderDetailViewModel>(
orderDetailModels, // the list of your order details models
OrderDetails, // the list of order details view models exposed by the Order view model
x => new OrderDetailViewModel(x), // factory method to create a view model
null); // do something here if you care when your view models are removed
When it comes to the question "Do I need another view model", my answer is this: If all your view is doing is showing the model data, there is no harm in binding directly to the order directly. Creating a ViewModel for this would be very much redundant. The time when the ViewModel needs to be created is when you have logic or state in the "order detail" screen that needs to be represented. Instead of adding that to the model, you create a ViewModel at that time.
As far as keeping those items in sync, Similar to GraemeF, I have created a Binder class that is uses reflection to bind two values together. It keeps my model and viewmodel properties in sync, and it can be used to keep other things in sync, like this particular collection. There is some overhead in creating a binder like this, but once it is done, you can specify data correlations in a functional way, which is really nice.