Getting error from login to master details page in xamarin.forms in view model? - mvvm

When i trying to navigate from login page to masterDetailpage, I am getting error says
"System.Reflection.TargetInvocationException
Message=Exception has been thrown by the target of an invocation."
I tried this in the login function when user successful logged in
async void Login()
{
try
{
var current = Connectivity.NetworkAccess;
if (current == NetworkAccess.Internet)
{
if (IsValidated)
{
await navigationRef.PushPopupAsync(new LoaderPage()).ConfigureAwait(false);
userDetails = await webServicesRepository.UserLogin(Phone, Password, "123113123", "Android").ConfigureAwait(false);
if (userDetails != null && userDetails.status == "200")
{
await navigationRef.PopPopupAsync().ConfigureAwait(false);
MasterDetailPage fpm = new MasterDetailPage
{
Master = new MainMenuPageMaster(),
Detail = new NavigationPage(new HomePage())
};
Application.Current.MainPage = fpm;
//Application.Current.MainPage = new NavigationPage(new MainMenuPage());
//await navigationRef.PushAsync(new MainMenuPage()).ConfigureAwait(false);
}
else
{
await navigationRef.PopPopupAsync().ConfigureAwait(false);
await Application.Current.MainPage.DisplayAlert(Constants.DISPLAY_POPUP_TITLE, Constants.NO_DATA_FOUND, Constants.DISPLAY_POPUP_BUTTON).ConfigureAwait(false);
}
}
else
{
await Application.Current.MainPage.DisplayAlert(Constants.DISPLAY_POPUP_TITLE, "You must fill all areas correctly!", Constants.DISPLAY_POPUP_BUTTON).ConfigureAwait(false);
}
}
else
{
await Application.Current.MainPage.DisplayAlert(Constants.DISPLAY_NETWORK_ERROR_TITLE, Constants.DISPLAY_NETWORK_ERROR_MESSAGE, Constants.DISPLAY_POPUP_BUTTON).ConfigureAwait(false);
}
}
catch(Exception ex)
{
Console.WriteLine(ex.InnerException.Message);
await Application.Current.MainPage.DisplayAlert(Constants.DISPLAY_POPUP_TITLE, Constants.NO_DATA_FOUND, Constants.DISPLAY_POPUP_BUTTON).ConfigureAwait(false);
}
}
MasterDetailPage :
<?xml version="1.0" encoding="utf-8" ?>
<MasterDetailPage 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.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="intSetSet.MainMenuPage"
xmlns:views="clr-namespace:XXXXXX"
NavigationPage.HasNavigationBar="False"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.UseSafeArea="true">
<MasterDetailPage.Master>
<views:MainMenuPageMaster x:Name="masterPage" Title="Menu" Icon="ListIcon.png" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<views:HomePage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
c#
public partial class MainMenuPage : MasterDetailPage
{
public MainMenuPage()
{
InitializeComponent();
try
{
masterPage.MenuItemsListView.ItemSelected += ListView_ItemSelected;
MessagingCenter.Subscribe<EventArgs>(this, "OpenMenu", args =>
{
IsPresented = !IsPresented;
});
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as MainMenuPageModel;
if (item == null)
return;
var page = (Page)Activator.CreateInstance(item.TargetType);
//var page = item.TargetType;
page.Title = item.Title;
Detail = new NavigationPage(page);
IsPresented = false;
masterPage.MenuItemsListView.SelectedItem = null;
}
}
ContentPage to generate List options:
<?xml version="1.0" encoding="utf-8" ?>
<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.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="XXXXX.MainMenuPageMaster"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.UseSafeArea="true">
<StackLayout>
<ListView x:Name="MenuItemsListView"
SeparatorVisibility="None"
x:FieldModifier="public"
HasUnevenRows="true"
ItemsSource="{Binding MenuItems}">
<ListView.Header>
<StackLayout BackgroundColor="#CEDAEE">
<StackLayout Orientation="Horizontal"
Padding="20">
<Image Margin="10,10,0,0"
Source="setsetlogo.png"
WidthRequest="80"
HeightRequest="80"
HorizontalOptions="Start"></Image>
<Label HorizontalOptions="StartAndExpand"
VerticalTextAlignment="Center"
Text="IntSetSet"
TextColor="White"
FontSize="24" />
</StackLayout>
<BoxView BackgroundColor="Teal"
HorizontalOptions="FillAndExpand"
HeightRequest="1"></BoxView>
</StackLayout>
</ListView.Header>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout HorizontalOptions="FillAndExpand"
BackgroundColor="#CEDAEE">
<StackLayout Padding="10,10"
Orientation="Horizontal">
<Image Source="{Binding Icon}"
WidthRequest="40"
HeightRequest="40"
VerticalOptions="Center"
HorizontalOptions="Start"></Image>
<Label VerticalOptions="Center"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Start"
HorizontalOptions="StartAndExpand"
TextColor="White"
Text="{Binding Title}"
FontSize="Medium" />
</StackLayout>
<BoxView BackgroundColor="Teal"
HorizontalOptions="FillAndExpand"
HeightRequest="1"></BoxView>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.Footer>
<StackLayout BackgroundColor="#CEDAEE" Orientation="Horizontal" HorizontalOptions="FillAndExpand">
<Button Command="{Binding LogoutCommand}" Text="LogOut" BackgroundColor="#CEDAEE" TextColor="Yellow" HorizontalOptions="EndAndExpand">
</Button>
<!--<Button Clicked="LogoutButton_Clicked" Text="LogOut" BackgroundColor="#CEDAEE" TextColor="Yellow" HorizontalOptions="EndAndExpand">
</Button>-->
</StackLayout>
</ListView.Footer>
</ListView>
</StackLayout>
</ContentPage>
C#
public partial class MainMenuPageMaster : ContentPage
{
public MainMenuPageMaster()
{
InitializeComponent();
BindingContext = new MainMenuPageViewModel();
}
}
View Model:
public class MainMenuPageViewModel : INotifyPropertyChanged
{
public ObservableCollection<MainMenuPageModel> MenuItems { get; set; }
public ICommand LogoutCommand { get; }
public MainMenuPageViewModel()
{
try
{
MenuItems = new ObservableCollection<MainMenuPageModel>(new[]
{
new MainMenuPageModel { Id = 0, Title = "Home", Icon="shop.png", TargetType= typeof(HomePage) },
new MainMenuPageModel { Id = 1, Title = "Profile", Icon="shop.png", TargetType= typeof(ProfilePage) },
new MainMenuPageModel { Id = 2, Title = "Referral History", Icon="paper_money.png", TargetType= typeof(ReferralHistoryPage) },
});
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
}
#region INotifyPropertyChanged Implementation
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged == null)
return;
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
I want to Navigate from the login page to master details page on successful login

Related

NET MAUI how to create a hamburger menu

I am trying to create a hamburger menu in xaml, but zero success. I was trying to use the samples provided [here][1], but zero success.
My idea is to create a view model that has a list of FlyoutItems then inject this view model to the AppShell.
public partial class ShellViewModel : ObservableObject
{
public List<FlyoutItem> FlyoutItems { get; private set; } = new List<FlyoutItem>();
public ShellViewModel()
{
AddMenuItems();
}
private void AddMenuItems()
{
var flyoutItems = new List<FlyoutItem>
{
new FlyoutItem
{
Title = "Item 1"
},
new FlyoutItem
{
Title = "Item 2"
}
};
FlyoutItems.AddRange(flyoutItems);
}
}
public partial class AppShell : Shell
{
private ShellViewModel viewModel => BindingContext as ShellViewModel;
public AppShell(ShellViewModel viewModel)
{
BindingContext = viewModel;
RegisterRoutes();
InitializeComponent();
}
private void RegisterRoutes()
{
Routing.RegisterRoute(PageRoutes.LoginPage, typeof(LoginPage));
Routing.RegisterRoute(PageRoutes.RegisterPage, typeof(RegisterPage));
Routing.RegisterRoute(PageRoutes.HomePage, typeof(MainPage));
Routing.RegisterRoute(PageRoutes.DetailsPage, typeof(PlayerDetailsPage));
Routing.RegisterRoute(PageRoutes.AddOrUpdatePage, typeof(AddOrUpdatePlayer));
}
}
In the XAML sometign like this
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="MauiUI.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiUI"
xmlns:pages="clr-namespace:MauiUI.Pages">
<Shell.ItemTemplate>
<DataTemplate>
<CollectionView BindingContext="{x:Reference shell}"
IsGrouped="True"
ItemsSource="{Binding FlyoutItems}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding Title}"
TextColor="White"
FontSize="18" />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</DataTemplate>
</Shell.ItemTemplate>
<ShellContent
Title="Amazons of Volleyball"
ContentTemplate="{DataTemplate pages:SplashPage}"
Route="HomePage" />
</Shell>
thnx
[1]: https://learn.microsoft.com/en-us/dotnet/maui/fundamentals/shell/flyout?view=net-maui-7.0
I am trying to create a hamburger menu in xaml, but zero success.
You can add this code in your AppShell.xaml:
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="MauiUI.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiUI"
xmlns:views="clr-namespace:MauiUI.Pages">
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
<ShellContent Title="Home"
Route="home"
ContentTemplate="{DataTemplate local:MainPage}" />
<ShellContent Title="NewPage1"
ContentTemplate="{DataTemplate pages:NewPage1}" />
</FlyoutItem>
</Shell>
Or you can add this code in your AppShell.xaml.cs:
public partial class AppShell : Shell    
{
  public AppShell ()        
{
        InitializeComponent ();
        
        FlyoutItem flyoutItem = new FlyoutItem ();
        flyoutItem.FlyoutDisplayOptions = FlyoutDisplayOptions.AsMultipleItems;
        
        flyoutItem.Items.Add (new ShellContent () { Title = "NewPage1", Content = new NewPage1 () });
        flyoutItem.Items.Add (new ShellContent () { Title = "home", Content = new MainPage () });
        
        myshell.Items.Add (flyoutItem);
        
}
    
}

Listview IsEnabled property not working in .Net maui

Listview IsEnabled property not working in .Net Maui. Please look into the below code.
<StackLayout>
<ListView x:Name="listView" ItemsSource="{Binding Source}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid ColumnDefinitions="100,*">
<Label Grid.Column="0" Text="{Binding Name}" />
<Switch Grid.Column="1" IsToggled="{Binding Enabled}"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Text="Button1" Clicked="Button_Clicked1"/>
<Button Text="Button2" Clicked="Button_Clicked2"/>
</StackLayout>
Code Behind
public partial class MainPage : ContentPage
{
//static public FoodViewModel Foods;
public MainPage()
{
InitializeComponent();
//Foods = new FoodViewModel();
this.BindingContext = new FoodViewModel();
}
private void Button_Clicked2(object sender, EventArgs e)
{
listView.IsEnabled = false;
}
private void Button_Clicked1(object sender, EventArgs e)
{
listView.IsEnabled = true;
}
}
In the upper code the Switch should be Enabled when listview enabled but im unable to toggle the switch.
Try this.BindingContext = this;
Try using Enabled property.
listView.Enabled = true;

Child property of an ObservableProperty is not updating

Something isn't right with the XAML but it's not sticking out at me.
I've been working on the layout of one of my .net Maui XAML pages. I added a collectionView when I noticed that the top data was no longer showing. The other pages are working fine.
What's weird is that the data is there and while running the app in debug mode if I highlight, shift-delete, then paste it back in the bound data appears. I also noticed if I change the {Binding EditEvent.name} by removing the "name" from EditEvent then adding it back on, the view displays the data as well.
But if I leave and navigate back in the data won't show up until I repeat the above process. It's like the viewModel isn't updating the view when the data changes. But if I force the view to update by deleting and re-pasting it will show it.
Anyone have an idea what possibly could be the issue?
I've got 2 ObservableProperties in my ViewModel:
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Newtonsoft.Json;
using SharedModels;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyApp.ViewModels
{
public partial class EditEventViewModel : ObservableObject
{
#region XAML page Observables
[ObservableProperty]
attEventDx editEvent;
[ObservableProperty]
ObservableCollection<groupReturn> groupsItems;
#endregion
// pass object to edit into this view
public async void SetEditEvent(attEventDx incomingEvent)
{
editEvent = incomingEvent;
//await LoadGroupsAsync();
}
...
}
And this is the view:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.Pages.EditEventPage"
Title="Edit Event"
xmlns:viewmodel="clr-namespace:MyApp.ViewModels"
xmlns:dm="clr-namespace:SharedModels;assembly=SharedModels"
x:DataType="viewmodel:EditEventViewModel"
NavigatedTo="ContentPage_NavigatedTo">
<VerticalStackLayout>
<Grid HorizontalOptions="Center" VerticalOptions="Start" Padding="0,40,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<Label Text="Event Name" VerticalOptions="Center" HorizontalOptions="Center" Grid.Column="0" Grid.Row="0"/>
<Entry Text="{Binding EditEvent.name}" WidthRequest="200" Grid.Column="1" Grid.Row="0"/>
<Label Text="Event Date" VerticalOptions="Center" HorizontalOptions="Center" Grid.Column="0" Grid.Row="1"/>
<Entry Text="{Binding EditEvent.happeningOn}" WidthRequest="200" Grid.Column="1" Grid.Row="1"/>
</Grid>
<Label Text="Selectable Groupings" VerticalOptions="Center" HorizontalOptions="Center" Padding="20"/>
<CollectionView ItemsSource="{Binding GroupsItems}" SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="dm:groupReturn">
<SwipeView>
<SwipeView.RightItems>
<SwipeItem Text="Delete" BackgroundColor="Red"/>
</SwipeView.RightItems>
<Grid Padding="0,5">
<Label Text="Groups"/>
<ScrollView>
<Frame>
<Frame.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:EditEventViewModel}}, Path=TapCommand}"
CommandParameter="{Binding .}" />
</Frame.GestureRecognizers>
<Label Text="{Binding groupName}" FontSize="20" FontAttributes="Bold"/>
</Frame>
</ScrollView>
</Grid>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
this is my xaml.cs for that page:
public partial class EditEventPage : ContentPage, IQueryAttributable
{
EditEventViewModel _vm;
attEventDx _editEvent;
public EditEventPage( EditEventViewModel vm)
{
InitializeComponent();
_vm = vm;
BindingContext = _vm;
}
public void ApplyQueryAttributes(IDictionary<string, object> query)
{
_editEvent = query["EditEvent"] as attEventDx;
}
private void ContentPage_NavigatedTo(object sender, NavigatedToEventArgs e)
{
_vm.SetEditEvent(_editEvent);
}
}
attEventDx for reference (sits in another shared project between Azure Functions and the mobile app):
namespace SharedModels
{
public class attEventDx
{
public Guid? publicId { get; set; }
public int? createdBy { get; set; }
public string name { get; set; }
public DateTime dateCreated { get; set; }
public DateTime? happeningOn { get; set; }
}
}
As I referred to this is the page that IS working:
xaml.cs:
public partial class EventPage : ContentPage
{
EventViewModel _vm;
public EventPage(EventViewModel vm)
{
InitializeComponent();
_vm = vm;
BindingContext= _vm;
}
private async void ContentPage_NavigatedTo(object sender, NavigatedToEventArgs e)
{
await _vm.LoadEventData();
}
private void ImageButton_Clicked(object sender, EventArgs e)
{
}
}
ViewModel:
public partial class EventViewModel : ObservableObject
{
#region XAML page Observables
[ObservableProperty]
ObservableCollection<attEventDx> eventItems;
[ObservableProperty]
attEventDx selectedEvent;
[ObservableProperty]
string text;
#endregion
public EventViewModel()
{
//EventItems = new ObservableCollection<attEventDx>();
}
[RelayCommand]
public async Task LoadEventData()
{
MyApp.globals.SetHttpClient();
try
{
var response = await MyApp.globals.httpClient.GetAsync(MyApp.globals.APIURL + "getEvents");
var allEvents = response.Content.ReadAsStringAsync().Result;
if (allEvents != null)
{
List<attEventDx> listOfEvents = JsonConvert.DeserializeObject<List<attEventDx>>(allEvents);
if (listOfEvents != null)
{
EventItems = new ObservableCollection<attEventDx>(listOfEvents);
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message + "\r\b" + ex.StackTrace);
}
}
[RelayCommand]
async Task Add()
{
await Shell.Current.GoToAsync($"{nameof(AddEventPage)}");
}
[RelayCommand]
async Task Tap(attEventDx sender)
{
selectedEvent = sender;
var navigationParameter = new Dictionary<string, object>
{
["EditEvent"] = selectedEvent
};
await Shell.Current.GoToAsync($"{nameof(EditEventPage)}", navigationParameter);
}
[RelayCommand]
async Task Refresh()
{
await LoadEventData();
}
}
And the view of the working page:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MyApp.EventPage"
Title="Events"
xmlns:viewmodel="clr-namespace:MyApp.ViewModels"
xmlns:dm="clr-namespace:SharedModels;assembly=SharedModels"
x:DataType="viewmodel:EventViewModel"
NavigatedTo="ContentPage_NavigatedTo">
<Grid RowDefinitions="100, Auto, 30, *"
ColumnDefinitions=".50*, .25*, .25*"
Padding="10">
<Image Grid.ColumnSpan="3"
Source="logo.png"
BackgroundColor="Transparent"/>
<ImageButton Source="plus.png" Grid.Row="0" Grid.Column="2" Scale=".7" Command="{Binding AddCommand}"></ImageButton>
<Label Text="New Event" Grid.Column="2" Grid.Row="0" HorizontalOptions="Center" VerticalOptions="End"></Label>
<!--<Entry Placeholder="Enter Text" Grid.Row="1" Text="{Binding Text}" />-->
<!--<Button Text="Search" Grid.Row="1" Grid.Column="1" />-->
<!--<Button Text="Add" Grid.Row="1" Grid.Column="2" Command="{Binding AddCommand}"/>-->
<Label Text="Upcoming Events" FontSize="22" Grid.Row="2"/>
<!--<Button Text="Refresh" Grid.Row="2" Grid.Column="2" Command="{Binding RefreshCommand}"/>-->
<CollectionView Grid.Row="3" Grid.ColumnSpan="3" ItemsSource="{Binding EventItems}" SelectionMode="None">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="dm:attEventDx">
<SwipeView>
<SwipeView.RightItems>
<SwipeItem Text="Delete" BackgroundColor="Red"/>
</SwipeView.RightItems>
<Grid Padding="0,5">
<Label Text="Event"/>
<ScrollView>
<Frame>
<Frame.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:EventViewModel}}, Path=TapCommand}"
CommandParameter="{Binding .}" />
</Frame.GestureRecognizers>
<Label Text="{Binding name}" FontSize="20" FontAttributes="Bold"/>
</Frame>
</ScrollView>
<Label Text="{Binding happeningOn}" HorizontalOptions="End" VerticalOptions="Center" Padding="0,0,5,0"></Label>
</Grid>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
Well, what ToolmakerSteve told me kind of worked, the items were initially displaying but not updating.
I then decided to build out another page in the app and do some experimenting along the way and figured out the issue.
When I created the new page by hand, I still had this issue and was doubting my sanity. I then partially copied in the page that was working and it worked! In comparing the two pages closely, I finally discovered what the problem was.
I was right, the CommunityToolkit's [ObservableProprerty] DOES work for all child items in an object; this is why I selected using this library from the start. I wasn't going crazy... (At least not on this)
This particular app was started a few months ago but then I got pulled into another project in another platform for a few months so what I had learned was partially forgotten when I picked it back up recently.
When you define a [ObservableProperty] like this:
[ObservableProperty]
myObject usedVariable;
The "usedVariable" will contain the data, but not the framework for INotifyPropertyChanged. CommunityToolkit builds out the framework on "UsedVariable".
While this code is "legal" in the ViewModel:
usedVariable = new myObject();
It will assign the data, but not the notification framework.
Instead it needs to be:
UsedVariable = new myObject();
Once the variable is defined with lowercase, you will never reference the variable that way again (as far as I can tell anyway). Instead, you will use the uppercase "UsedVariable".
When I referenced the lowercase version of the variable, I didn't see the data on the app page when it started. However, if I had the page open and I removed the XAML code for that control and pasted it back in, the data did show.
It's always something simple that causes the most grief...

How to bind attributes values in MAUI component

I'm trying to make a windows-like navigation item.
This is the implementation:
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="NavItem.NavItem"
xmlns:local="clr-namespace:NavItem"
x:DataType="local:NavItem">
<Frame HeightRequest="50" CornerRadius="6" BackgroundColor="{StaticResource Tertiary}" BorderColor="{StaticResource Secondary}" Padding="10">
<Frame.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_Tapped" />
</Frame.GestureRecognizers>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Label x:Name="LblText" Text="{Binding Text}" Grid.Column="0" TextColor="{StaticResource White}" />
<Label Text=">" Grid.Column="1" TextColor="{StaticResource White}" FontSize="16" />
</Grid>
</Frame>
</ContentView>
public partial class NavItem : ContentView
{
string text;
public string Text
{
get => text;
set { text = value; OnPropertyChanged(); }
}
public string PageName { get; set; }
public NavItem()
{
InitializeComponent();
}
private async void TapGestureRecognizer_Tapped(object sender, EventArgs e)
{
await Shell.Current.GoToAsync(PageName);
}
}
<VerticalStackLayout>
<local:NavItem Text="Page 1" PageName="Page1" />
<local:NavItem Text="Page 2" PageName="Page2" />
</VerticalStackLayout>
The navigation is ok but the binding fails to set Text property of label LblText.
So this is the rendering:
EDIT: I also tried with a bindable attribute, same result
public string Text
{
get => (string)GetValue(TextProperty);
set { SetValue(TextProperty, value); OnPropertyChanged(); }
}
public static readonly BindableProperty TextProperty =
BindableProperty.Create(nameof(Text), typeof(string), typeof(NavItem), "", BindingMode.TwoWay);
I just had to set the binding context to itself:
public NavItem()
{
InitializeComponent();
BindingContext = this;
}

Mvvm Windows Phone 8 command Error: BindingExpression path error: 'SalvarCommand'

My commands are pointing to the Model class and not for ModelView
System.Windows.Data Error: BindingExpression path error: 'SalvarCommand' property not found on 'SuperListaW8.Model.ListaItem' 'SuperListaW8.Model.ListaItem'
EditListaPage.xaml
<phone:PhoneApplicationPage
x:Class="SuperListaW8.View.EditListaPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wm="clr-namespace:System.Windows.Controls;assembly=WindowsPhoneWatermarkTextBoxControl"
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WP8"
FontFamily="{StaticResource PhoneFontFamilyNormal}"
FontSize="{StaticResource PhoneFontSizeNormal}"
Foreground="{StaticResource PhoneForegroundBrush}"
SupportedOrientations="Portrait" Orientation="Portrait"
DataContext="{Binding Source={StaticResource Locator}, Path=ListaViewModel}"
mc:Ignorable="d"
shell:SystemTray.IsVisible="True">
EditListaPage.xaml --> block text
<TextBox Grid.Column="1" Background="#f3f3f3" BorderBrush="#f3f3f3" VerticalAlignment="top">
<i:Interaction.Triggers>
<i:EventTrigger EventName="TextChanged">
<cmd:EventToCommand Command="{Binding Path=SalvarCommand, Mode=TwoWay}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
ViewModelLocator.cs
namespace SuperListaW8.ViewModel
{
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (!SimpleIoc.Default.IsRegistered<IDataService>())
{
SimpleIoc.Default.Register<IDataService, DataService>();
//SimpleIoc.Default.Register<INavigationService>(() => new NavigationService());
}
SimpleIoc.Default.Register<ListaViewModel>();
}
public ListaViewModel ListaViewModel
{
get
{
return ServiceLocator.Current.GetInstance<ListaViewModel>();
}
}
public static void Cleanup() { }
}
}
ListaViewModel.cs
namespace SuperListaW8.ViewModel
{
public class ListaViewModel : ViewModelBase
{
public RelayCommand SalvarCommand { get; private set; }
public ListaViewModel(IDataService dataService)
{
_dataService = dataService;
SalvarCommand = new RelayCommand(() =>
{
System.Diagnostics.Debugger.Break();
});
}
}
}
My commands are being sought in the model and not in the ViewModel ListaItem ListaViewModel. Can anyone help me?
You could name the ListBox and in the Binding you reference it with ElementName, and in Path you use DataContext.DetailsVisibility
<ListBox x:Name="listBox" ItemsSource="{Binding Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Title}" />
<TextBlock Text="{Binding Details}"
Visibility="{Binding ElementName=listBox,
Path=DataContext.DetailsVisibilty}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>