Reputation: 15850
I'm somewhat new to Xamarin development. Trying to accomplish a fairly simple task: in XAML, data-bind the menu page to a ViewModel that is injected into my menu-page.
Here's what my XAML looks like. Intellisense recognizes _viewModel and shows its properties further down in it the ListView
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
BindingContext="{x:Reference_viewModel}"
x:Class="SFC.Cliente.Mobile.Views.MenuPage"
x:Name="Menu"
Title="Menu">
<StackLayout VerticalOptions="FillAndExpand">
<ListView x:Name="ListViewMenu" HasUnevenRows="True" ItemsSource="{Binding MenuItems}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid Padding="10">
<Label Text="{Binding Title}" FontSize="20"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
Here's what my code behind looks like. ViewModel is injected into page's code-behind without issues and is not null
namespace SFC.Client.Mobile.Views
{
// Learn more about making custom code visible in the Xamarin.Forms previewer
// by visiting https://aka.ms/xamarinforms-previewer
[DesignTimeVisible(visible:false)]
public partial class MenuPage : ContentPage
{
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
private readonly MenuItemsViewModel _viewModel;
public MenuPage(MenuItemsViewModel viewModel)
{
_viewModel = viewModel;
InitializeComponent();
ListViewMenu.ItemSelected += async (sender, e) =>
{
if (e.SelectedItem == null)
return;
var id = ((HomeMenuItem) e.SelectedItem).Id;
var rootPage = (MainPage) Application.Current.MainPage;
await rootPage.NavigateFromMenu(id);
};
}
}
}
Here's the exception that I am getting during InitializeComponent(). I would like to wire data-binding thru XAML, not thru code. I've tried making _viewModel to be public or private, property or member: no change. What am I doing wrong?
{System.Collections.ListDictionaryInternal}
-2146233088
(null)
(null)
"Position 7:14. Can not find the object referenced by_viewModel
"
"Xamarin.Forms.Xaml"
" at Xamarin.Forms.Xaml.Reference.ProvideValue(System.IServiceProvider serviceProvider) [0..."
{System.Reflection.MonoMethod}
Upvotes: 4
Views: 5413
Reputation: 6088
I have to agree with Ivan Ičin above.
I am not sure why it is so important to set the binding context on the XAML when you can easily just do this:
public partial class MenuPage : ContentPage
{
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable
// private readonly MenuItemsViewModel _viewModel;
public MenuPage(MenuItemsViewModel viewModel)
{
BindingContext = viewModel; // <---------- changed line
...
}
}
UPDATE: found possible solution.
Set a static property on your page, e.g.:
public static MenuItemsViewModel BindingContextInstance { get; set; } = null;
Assign your view model to the above static member BEFORE you call InitializeComponent()
:
public MenuPage(MenuItemsViewModel viewModel)
{
BindingContextInstance = viewModel;
InitializeComponent();
...
}
Then in the XAML, add a new xmlns entry and set BindingContext:
xmlns:views="clr-namespace:SFC.Client.Mobile.Views"
BindingContext="{x:Static views:MenuPage.BindingContextInstance}"
Note: This does not work for auto complete in the current stable version of Visual Studio for Mac (8.1.5.9), but does work in the current Preview version (8.2) and in the current version of Visual Studio 2019 (16.1.6) on Windows. Set your update channel to Preview in Visual Studio for Mac in the Visual Studio Update dialog and when the updates are downloaded, Restart and Install updates.
Upvotes: 2
Reputation: 9990
I don't think that you can bind like that. Here is an example of how view models are bound in XAML: Set BindingContext to ViewModel in XAML on Xamarin.Forms
Upvotes: 0