Avoiding Locator Bloat - mvvm-light

Just starting a new project with MVVM light after a few years hiatus. I am wiring up my first VM using the ViewModelLocator and I see that for each new view model we need to create a new property. I am just wondering how to avoid this as the app may end up having quite a few view models (50+). I have gotten it to work using a value converter but then I loose intellisence in the XAML editor.
Any examples from those who may have a solution to this is appreciated.
Note - here is a solution using a value converter, so I can then just pass the parameter into some IoC and get the VM, but then I loose intellisense (WelcomeTitle gets the squiggle).
<Window x:Class="My.MainWindow"
DataContext="{Binding Source={StaticResource Locator},
Converter={StaticResource Locator}, ConverterParameter='foo'}">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<TextBlock FontSize="36"
FontWeight="Bold"
Foreground="Purple"
Text="{Binding WelcomeTitle}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
TextWrapping="Wrap" />
</Grid>
</Window>
Update:
Here is another approach, better than using a converter, but still suffers from WelcomeTitle squiggle because the XAML editor does not know the type. I wonder if this effects "blendability"? (I do not have blend handy.)
http://maartendewilde.blogspot.com/2011/01/auto-viewmodel-binding-with-ninject.html
Thanks

For the intellisense, you can try yet more boilerplate on the resources?
/// <summary>
/// Class to contain things
/// </summary>
/// <typeparam name="T">UserID</typeparam>
/// <typeparam name="TK">UserName</typeparam>
public class MyDictionary<T,TK> : Dictionary<T,TK>
or what about using a shared resource dictionary to make intellisense happy?
Dependency injection is a good way to reduce redundant locator code. It involves a generic way of registering service or model providers. From the MSDN.
If you have to create a new property for each view model, it may indicate a weakness in your actual model. When working with VMs I usually find that they are reductive, in that the model contains all pertinent data, and view models get constructed as a subset of properties important to that view.
It is not uncommon for a large project to have 50+ view models.

Related

mvvmcross xamarin.forms PictureChooser

I am trying to develop a photo app using the PictureChooser plugin. I see that the sample uses Xamarin.iOS. I've googled for examples where the plugin uses Xamarin.Forms but can't find any. I understand how binding works for labels, text editors, and buttons; however, the binding btw the page's image control and the viewmodel's byte[] has got me stomped.
DAA.UI project:
In CameraPage.XAML:
<Image x:Name="MyImage"
Source="{Binding Bytes, Converter={StaticResource InMemoryImage}}"
Aspect="Fill"
HeightRequest="{OnPlatform iOS=300, Android=250}"
WidthRequest="{OnPlatform iOS=300, Android=250}"
HorizontalOptions="Center" />
In App.XAML:
<?xml version="1.0" encoding="utf-8" ?>
<Application
x:Class="DamageAssessmentApp.UI.App"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="clr-namespace:MvvmCross.Forms;assembly=MvvmCross.Forms"
xmlns:resources="clr-namespace:DAA.UI.Resources"
xmlns:local="using:DAA.UI"
xmlns:nativeValueConverters="using:DAA.UI.NativeValueConverters">
<Application.Resources>
<!-- Application resource dictionary -->
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<resources:Colors />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
<nativeValueConverters:NativeInMemoryImageValueConverter x:Key="InMemoryImage"/>
</Application.Resources>
</Application>
Value Converter file:
using MvvmCross.Forms.Converters;
namespace DAA.UI.NativeValueConverters
{
public class NativeInMemoryImageValueConverter : MvxNativeValueConverter<MvxInMemoryImageValueConverter>
{
}
}
The compiler can't find MvxInMemoryImageValueConverter in the value converter file.
If you are using MVVMCross you should find an example that works with Xamarin.Forms, in which case a good place to start it's their Github.
Or you have to implement it in each platform and use a DependencyService to get the implementation
Other Alternatives
Xamarin Community Toolkit
Another alternative for a camera App is Xamarin Community Toolkit Camera View. In that same link there is an example. But there are more examples in their Github. This is fully compatible with Xamarin.Forms and brings a little more control over the CameraView
Xamarin.Essentials
Xamarin.Essentials offers the MediaPicker that let's the user upload a photo from the gallery or take a new one. But the action of the photo in handled by the OS, so for you it's like a black box. You call the function, and get the photo.

Windows Template Studio MVVMLight accessing ViewModel from Details page

I'm using Windows Template Studio V3.0 the create a UWP App using MVVMLight that implements a Master/Detail page. I'm sure I'm going to kick myself but I can't work out how to access the ViewModel from the Details page. I need to access a property on the View Model to set the Visibility of some XAML elements.
In previous versions of the WTS I could use the Locator to access the ViewModel as follows:
<TextBlock
Margin="8"
Text="{x:Bind MasterMenuItem.Name , Mode=OneWay}"
Style="{StaticResource BodyTextBlockStyle}"
Visibility="{Binding Source={StaticResource Locator}, Path=DriverDetailsViewModel.EditMode, Converter={StaticResource InverseBoolToVisibilityConverter}}" />
In V3 of WTS the implementation of the Locator has changed and does not appear to accessible as a Static Resource?
As I suspected, after studying the WTS code a bit more I realised that I can access the ViewModelLocator from the XAML code-behind. I just needed to add the following to my detailsview code-behind:
private DriverDetailsViewModel ViewModel
{
get { return ViewModelLocator.Current.DriverDetailsViewModel; }
}
Then the following XAML works
Visibility="{x:Bind ViewModel.IsEditMode, Mode=OneWay, Converter={StaticResource InverseBoolToVisibilityConverter}}"

Specify design time binding context in a GridTemplateColumn

I'm working on a Xamarin.Forms project. In my xaml page, order to avoid "Cannot resolve property 'xxx'" warning, I've set a design-time data context.
In this page I have a SfDataGrid object.
In the following code snippet, the text property of the custom entry is binding to the Quantity field of a Part item. The Parts object is an ObservableCollection<Part>.
<xForms:SfDataGrid ItemsSource="{Binding Parts}" AutoGenerateColumns="false" Margin="0"
ScrollingMode="PixelLine"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" >
<xForms:SfDataGrid.Columns>
<xForms:GridTextColumn MappingName="ProductName" HeaderText="Product"
HeaderTextAlignment="Start" ColumnSizer="Star"
TextAlignment="Start" Padding="5,0,5,0"/>
<!--#region Quantity column -->
<xForms:GridTemplateColumn MappingName="Quantity" HeaderText="Quantity"
HeaderTextAlignment="Center"
ColumnSizer="Auto" Padding="0" >
<xForms:GridTemplateColumn.CellTemplate>
<DataTemplate>
<controls:CustomEntry Text="{Binding Quantity, Mode=TwoWay,
Converter={StaticResource NullableDouble}}"
Keyboard="Numeric" HorizontalTextAlignment="Center"
VerticalOptions="End"/>
</DataTemplate>
</xForms:GridTemplateColumn.CellTemplate>
</xForms:GridTemplateColumn>
<!--#endregion -->
</xForms:SfDataGrid.Columns>
</xForms:SfDataGrid>
The warning is displayed under the Quantity word in Text={Binding Quantity, Mode...
What should I do to avoid the warning for the binding used in the cell templates?
Should I add a BindingContext="{d:DesignInstance models:Part}", or d:DataContext="{d:DesignInstance models:Part}" on each field ?
Hi Crusty Applesniffer,
Thanks for using Syncfusion Product.
We have checked your query with following details.
By using SfDataGrid have created the GridTemplateClolumn and added CustomEntry as DataTemplate in XAML page
Text property of this custom entry is binding to the double type
property named as OrderId
We have set this Text property binding
Mode as TwoWay, And we have written the converter for this property.
And we have added the Xaml
Complilation([XamlCompilation(XamlCompilationOptions.Compile)]) Tag in .cs of the XAML
class file.
But unfortunately, We are unable to reproduce the “Cannot resolve property 'xxx'" warning” from our side, So Kindly provide More details in order to reproduce the issue.
Have you enabled any Style Cop or FxCop rule set in your application
? If yes, Mention those rule set details.
Type of property you have used to bind the Custom Entry Text Property.
SfDataGrid product version that you are currently using.
If possible kindly provide us the Issue replicating sample or modify the attached sample to replicate the issue.
We have prepared the sample as per your requirement, Do check and let us know Is there anything needs to add more to reproduce “Cannot resolve property 'xxx'" warning” issue.
Sample Link : http://www.syncfusion.com/downloads/support/directtrac/general/ze/DataGrid-1806700714
Regards,
Vigneshkumar R

What is the best way to create the MasterDetailPage menu items in Xamarin.Forms

I'm using a MasterDetailPage in my Xamarin.Forms application.
To creat the menu items, I use buttons
<MasterDetailPage.Master>
<ContentPage Title="Menu">
<StackLayout Orientation="Vertical">
<Button Text="Club-House" Command="{Binding ClubHouseCommand}" />
<Button Text="Parcours" />
<BoxView VerticalOptions="CenterAndExpand" />
<Button Text="A propos" Command="{Binding AProposCommand}" VerticalOptions="End" />
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
Is there a better way to do it ? I was thinking about something more menuish like MenuItem or else.
Thanks
There is nothing standard for implementing a menu in the Master page.
You can use
ListView
StackLayout
Grid
Or a combination. StackLayout and ListView will most likely be your best options. Personally I go for a StackLayout because it's quicker to code and render than a ListView, which may come with more issues than advantages. However if I have a large menu (which I try to avoid), ListView may be quicker to code. But ListViews are generally meant for dynamically loaded data, not static.
As for the elements, the most common will be
Button
Label
While buttons are designed for clicking, sometimes I move to label's if I don't want to have to undo all the default styling, and use the TapGestureRecognizer.
You can create a new User Control for a menu item, to avoid code replication.
All up, there is no standard. Make it easy to code and understand, and quick to render. How you do that, depends on your requirements.

Implementing UWP flyout splitview using masterdetailview in prism?

I am a complete noob to xamarin :)
So was wondering if someone could point me to right resources.
To be short, I want to implement something like this in prism using Xamarin MasterDetailPage.
Using the master detail sample here, the hamburger menu doesn't act as a fly out.
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="clr-namespace:Prism.Mvvm;assembly=Prism.Forms"
prism:ViewModelLocator.AutowireViewModel="True"
x:Class="HelloWorld.Views.MyMasterDetail">
<MasterDetailPage.Master>
<ContentPage Title="Default">
<StackLayout>
<Button Text="ViewA" Command="{Binding NavigateCommand}" CommandParameter="MyNavigationPage/ViewA?id=A" />
<Button Text="ViewB" Command="{Binding NavigateCommand}" CommandParameter="MyNavigationPage/ViewB?id=B" />
<Button Text="ViewC" Command="{Binding NavigateCommand}" CommandParameter="MyNavigationPage/ViewC?id=C" />
</StackLayout>
</ContentPage>
</MasterDetailPage.Master>
</MasterDetailPage>
Right now, though there is enough space, it shows something like
(just as a sample, I am not using SplitViewMenu at all)
I need icons/some small text to show initially and on clicking hamburger, it should expand (you know just like the first link/ groove music app behavior).
Tips?
Right now, though there is enough space, it shows something like
In my experience, if you have assigned the Symbol property for SimpleNavMenuItem, the possible reason is you haven't imported the Themes file Generic.xaml under Themes folder
This file includes templates, styles for custom controls. For example, for NavMenuItem's template, FontIcon's Glyph property needs to be assigned correctly here:
<DataTemplate x:Key="NavMenuItemTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<FontIcon FontSize="16" Glyph="{Binding Path=SymbolAsChar}" VerticalAlignment="Center"
HorizontalAlignment="Center" ToolTipService.ToolTip="{Binding Path=Label}" />
<TextBlock Grid.Column="1" Text="{Binding Path=Label}" VerticalAlignment="Center" />
</Grid>
</DataTemplate>
While SimpleNavMenuItem class's SymbolAsChar property is based on Symbol's value:
public sealed class SimpleNavMenuItem : INavigationMenuItem
{
......
public Symbol Symbol { get; set; }
public char SymbolAsChar => (char) Symbol;
......
}
And if you still can make it work, please share a demo:)
I've sort of been looking for something like this myself since I can't hide the NavigationBar shown in the Master page of the MasterDetailPage when i run it on a Windows 10 Mobile device (I can hide for PC though). So basically, I'm looking into eventually building my own version of the MasterDetailPage.
Since I have not built it yet, I can't tell you exactly how to achieve what you're asking, but I do know that it will require you to either:
Write your own custom renderer for MasterDetailView or,
Write a new control and its renderer
In both cases, your renderer will involve creating and manipulating a new SplitView (which is the native UWP control that your SplitViewMenu example is extending). There's a tutorial for creating the actual UWP control here. If you havent learned about Xamarin's renderers yet, they are the "Translator" and "Interpreter" between a Xamarin.Forms control and a given platform's native control. I suspect Xamarin will eventually rewrite their MastDetailPage renderer for UWP to use a SplitView as a base, but who knows when that will be. Xamarin also has an open source SDK for Xamarin.Forms (as well as the others) on GitHub so you can study the MasterDetailPageRenderer for UWP.

Resources