Issue with showing the Image - xaml

My code is not working as I expected, data binding is working with other fields and properties but my image is not showing. Below the code, you can see the app output.
Here is the code for XAML:
<StackLayout Padding="20">
<Label Text="Id" TextColor="Red" />
<Editor BindingContext="{x:Reference Name=MyPage}" Text="{Binding obj.id}" IsReadOnly="True" />
<Label Text="First Name" TextColor="Red"/>
<Editor BindingContext="{x:Reference Name=MyPage}" Text="{Binding obj.first_name}" IsReadOnly="True"/>
<Label Text="Last Name" TextColor="Red"/>
<Editor BindingContext="{x:Reference Name=MyPage}" Text="{Binding obj.last_name}" IsReadOnly="True"/>
<Label Text="Email" TextColor="Red"/>
<Editor BindingContext="{x:Reference Name=MyPage}" Text="{Binding obj.email}" IsReadOnly="True"/>
<Editor BindingContext="{x:Reference Name=MyPage}" Text="Image" IsReadOnly="True"/>
<Image BindingContext="{x:Reference Name=MyPage}" Source="{Binding obj.avatar}"/>
</StackLayout>

You code looks well and you can directly binding a string to Source of image, I wrote a demo to test and you can check the code here:
In code behind:
public partial class MainPage : ContentPage
{
public MyModel obj { get; set; }
public MainPage()
{
obj = new MyModel();
obj.id = "idTest";
obj.first_name = "alex";
obj.last_name = "allen";
obj.email = "abc.com";
obj.avatar = "http://image10.bizrate-images.com/resize?sq=60&uid=2216744464";
InitializeComponent();
}
}
public class MyModel {
public string id { get; set; }
public string first_name { get; set; }
public string last_name { get; set; }
public string email { get; set; }
public string avatar { get; set; }
}
And in Xaml, the same as yours:
<?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="App150.MainPage"
x:Name="MyPage"
>
<StackLayout Padding="20">
<Label Text="Id" TextColor="Red" />
<Editor BindingContext="{x:Reference Name=MyPage}" Text="{Binding obj.id}" IsReadOnly="True" />
<Label Text="First Name" TextColor="Red"/>
<Editor BindingContext="{x:Reference Name=MyPage}" Text="{Binding obj.first_name}" IsReadOnly="True"/>
<Label Text="Last Name" TextColor="Red"/>
<Editor BindingContext="{x:Reference Name=MyPage}" Text="{Binding obj.last_name}" IsReadOnly="True"/>
<Label Text="Email" TextColor="Red"/>
<Editor BindingContext="{x:Reference Name=MyPage}" Text="{Binding obj.email}" IsReadOnly="True"/>
<Editor BindingContext="{x:Reference Name=MyPage}" Text="Image" IsReadOnly="True"/>
<Image BindingContext="{x:Reference Name=MyPage}" Source="{Binding obj.avatar}"/>
</StackLayout>
</ContentPage>
If your image url starts with http, you should add android:usesCleartextTraffic="true" to application tag in manifest file.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.app150">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="28" />
<application android:label="App150.Android" android:usesCleartextTraffic="true"></application>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
And in iOS, you should Configure ATS Options.
I uploaded my sample project here, feel free to ask me if you have any question.

Related

Command Binding for removing item from list view in XAML

I am trying to bind a command to my button so it can delete item from my list view.
My xaml looks like this
<?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="TradeMaker.Pages.AddItem"
Title="AddItem">
<Grid MaximumWidthRequest="800" ColumnDefinitions="*" RowDefinitions="auto,*, auto, auto" >
<SearchBar Grid.Column="0" Grid.Row="0" x:Name="searchBar"/>
<ListView x:Name="searchResult"
Grid.Row="1"
ZIndex="0"
BackgroundColor="AliceBlue"
Opacity="100"
ItemsSource="{Binding SelectedProducts}"
Header="{Binding .}"
SelectionMode="Single" >
<ListView.HeaderTemplate>
<DataTemplate>
<Grid ColumnDefinitions="410,130,130,130">
<Label Grid.Column="0" Text="Item" FontSize="14" HorizontalTextAlignment="Center" />
<Label Grid.Column="1" Text="Quantity" FontSize="14" HorizontalTextAlignment="Center"/>
<Label Grid.Column="2" Text="Total" FontSize="14" HorizontalTextAlignment="Center"/>
<Label Grid.Column="3" Text="Delete" FontSize="14" HorizontalTextAlignment="Center"/>
</Grid>
</DataTemplate>
</ListView.HeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid ColumnDefinitions="410, 130,130,130 ">
<Label Text="{Binding Title}" Grid.Column="3" FontAttributes="Bold" VerticalTextAlignment="Center" HorizontalTextAlignment="Start"/>
<Entry Text="{Binding Quantity}" Grid.Column="1" VerticalTextAlignment="Center" HorizontalTextAlignment="Center" />
<Label Text="{Binding Total}" Grid.Column="2" VerticalTextAlignment="Center" HorizontalTextAlignment="Center"/>
<Button Grid.Column="0" VerticalOptions="Center" HorizontalOptions="Center" BackgroundColor="LightGray"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ListView x:Name="resultCollection"
Grid.Row="1"
ZIndex="1"
BackgroundColor="AntiqueWhite"
Opacity="100"
ItemsSource="{Binding Products}"
SelectionMode="Single">
<ListView.ItemTemplate >
<DataTemplate>
<ViewCell >
<VerticalStackLayout Margin="5" >
<Label Text="{Binding Title, StringFormat='Name: {0}'}" />
<Label Text="{Binding price}"/>
</VerticalStackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Label Grid.Row="2" x:Name="dataLabe" Text="{Binding SubTotal}"/>
<Button Grid.Row="3" x:Name="next" Command="{Binding DeleteSelected}" />
</Grid>
</ContentPage>
And the code behind file is this
ProductsManager productsManager { get; }= new ProductsManager();
public AddItem()
{
InitializeComponent();
BindingContext = productsManager;
}
and the view model called productsmanager is as follow
public class ProductsManager:INotifyPropertyChanged
{
private ObservableCollection<Product> products;
private ObservableCollection<Product> selectedProducts;
public ObservableCollection<Product> Products { get => products; set { products = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Products))); } }
public ObservableCollection<Product> SelectedProducts { get=>selectedProducts; set { selectedProducts = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedProducts))); } }
public ProductsManager()
{
products = new ObservableCollection<Product>();
selectedProducts = new ObservableCollection<Product>();
}
private string subTotal="0";
public string SubTotal { get => subTotal; }
public void GetTotal()
{
float x = 0;
if (selectedProducts.Count > 0)
{
foreach (var item in selectedProducts)
{
var z = float.Parse(item.Total, System.Globalization.NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
x += z;
subTotal = x.ToString();
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SubTotal)));
}
}
}
public ICommand DeleteSelected{ get; set; }
private Product _selectedProduct;
public event PropertyChangedEventHandler PropertyChanged;
}
I can from above files add products to the resultCollection list view and from there select and add a product item in the searchResult list view. But I cannot figure out how to delete the product item from the searchResult list.

What is the correct way to use RelativeSource in the outer tag?

I want to avoid repeating Source={RelativeSource AncestorType={x:Type vm:MainViewModel}} in the following.
<SwipeView ... xmlns:vm="clr-namespace:Todo.ViewModel">
<SwipeView.LeftItems>
<SwipeItems>
<SwipeItem Text="Delete"
Command="{Binding DeleteCommand,Source={RelativeSource AncestorType={x:Type vm:MainViewModel}}}" />
</SwipeItems>
</SwipeView.LeftItems>
<Grid Padding="0,5">
<Frame >
<Frame.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding TapCommand,Source={RelativeSource AncestorType={x:Type vm:MainViewModel}}}"/>
</Frame.GestureRecognizers>
</Frame>
</Grid>
</SwipeView>
I do the following but it does not work as expected.
<SwipeView ... xmlns:vm="clr-namespace:Todo.ViewModel"
BindingContext="{Binding Source={RelativeSource AncestorType={x:Type vm:MainViewModel}}}"
>
<SwipeView.LeftItems>
<SwipeItems>
<SwipeItem Text="Delete" Command="{Binding DeleteCommand}" />
</SwipeItems>
</SwipeView.LeftItems>
<Grid Padding="0,5">
<Frame >
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding TapCommand}" />
</Frame.GestureRecognizers>
</Frame>
</Grid>
</SwipeView>
Repo
Use the following repo to avoid getting inconsistent results (among us) and to make sure we are talking in the same scope.
https://github.com/pstricks-fans/Todo
Here are the relevant parts:
MySwipeView:
public partial class MySwipeView : SwipeView
{
public MySwipeView()
{
InitializeComponent();
}
}
<SwipeView ...
x:Class="Todo.CustomControls.MySwipeView"
xmlns:vm="clr-namespace:Todo.ViewModel"
>
<SwipeView.LeftItems>
<SwipeItems>
<SwipeItem
Text="Delete"
Command="{Binding DeleteCommand,Source={RelativeSource AncestorType={x:Type vm:MainViewModel}}}"
CommandParameter="{Binding .}"/>
</SwipeItems>
</SwipeView.LeftItems>
<Grid Padding="0,5">
<Frame >
<Frame.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding TapCommand,Source={RelativeSource AncestorType={x:Type vm:MainViewModel}}}"
CommandParameter="{Binding .}"/>
</Frame.GestureRecognizers>
<Label Text="{Binding .}" FontSize="24"/>
</Frame>
</Grid>
</SwipeView>
MainPage:
public partial class MainPage : ContentPage
{
public MainPage(MainViewModel vm)
{
InitializeComponent();
BindingContext = vm;
}
}
<ContentPage ...
xmlns:local="clr-namespace:Todo.CustomControls"
xmlns:vm="using:Todo.ViewModel"
x:DataType="vm:MainViewModel"
>
<Grid ... >
<CollectionView ... >
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type x:String}">
<local:MySwipeView />
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>
MainViewModel:
public partial class MainViewModel : ObservableObject
{
[RelayCommand]
void Delete(string s){}
[RelayCommand]
async Task Tap(string s){}
}
In your case, SwipeView is being used inside an ItemTemplate. You MUST NOT change its BindingContext; that has to be the associated Item.
Therefore, your original goal is NOT POSSIBLE; we can simplify the "Source" expression, but we cannot eliminate it.
Simplest I know is:
Command="{Binding VM.DeleteCommand, Source={x:Reference thePage}}"
Explanation: On "thePage", finds property "VM", which contains a property "DeleteCommand". Make the following changes to MainPage.
<ContentPage
...
x:Name="thePage"
x:Class="MainPage">
class MainPage : ContentPage
{
// You can change this name. Be sure to use same name in XAML above.
public property MainViewModel VM { get; set; }
public MainPage(MainViewModel vm)
{
InitializeComponent();
// Put this line BEFORE set BindingContext. Used by XAML.
VM = vm;
BindingContext = vm;
}
At first, the format of binding to an ancestor in the official document is something like {Binding Source={RelativeSource AncestorType={x:Type local:PeopleViewModel}}, Path=DeleteEmployeeCommand}
And then you can try to set the SwipeView's binding context in the construction method instead of the binding way you used.
I have done a sample to test, and the binding worked well:
The MySwipeView.cs :
public partial class MySwipeView : SwipeView
{
      public ICommand TestCommand { get; private set; }
      public MySwipeView()
      {
            InitializeComponent();
            TestCommand = new Command<string>(Test);
//BindingContext = this;
            BindingContext = new MyViewModel();
      }
      void Test(string print)
      {
            Debug.WriteLine("============"+print);
      }
}
The MySwipeView.xaml:
<SwipeView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiAppTest.MySwipeView"
>
<SwipeView.LeftItems>
<SwipeItems>
<SwipeItem
Text="Delete"
Command="{Binding DeleteCommand}"
CommandParameter="xxxxxxxxx"/>
</SwipeItems>
</SwipeView.LeftItems>
<Grid Padding="0,5">
<Frame >
<Frame.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding TapCommand}"
CommandParameter="xxxxxxxx"/>
</Frame.GestureRecognizers>
<Label Text="xxxxxxxx" FontSize="24"/>
</Frame>
</Grid>
</SwipeView>
The MainPage.xaml:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiApp21"
x:Class="MauiApp21.MainPage">
<HorizontalStackLayout>
<local:MySwipeView/>
</HorizontalStackLayout>
</ContentPage>
The MyViewModel.cs:
public partial class MyViewModel : ObservableObject
{
[RelayCommand]
void Delete(string value) { Debug.WriteLine("===========Delete"); }
[RelayCommand]
void Tap(string value) { Debug.WriteLine("===============Tap"); }
}
No matter the BindingContext is this or the MyViewModel, the command will run successfully.

RelativeSource in MAUI control not bound

I'm going through simple example explained in video:
https://youtu.be/5Qga2pniN78?t=961
At 16. minute (timestamp in link above), he implements the Delete Command on SwipeItem.
In my local project, everything worked so far, but Delete Command is never triggered. I checked source generators, DeleteCommand exists.
My XAML:
<?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="MauiApp1.MainPage"
xmlns:viewmodel="clr-namespace:MauiApp1.ViewModel"
x:DataType="viewmodel:MainViewModel">
<Grid RowDefinitions="100, Auto, *"
ColumnDefinitions=".75*, .25*"
Padding="10"
RowSpacing="10"
ColumnSpacing="10">
<Image Grid.ColumnSpan="2" Source="tom.jpg"
BackgroundColor="Transparent"></Image>
<Entry Placeholder="Enter task" Grid.Row="1" Text="{Binding Text}"></Entry>
<Button Text="Add" Grid.Row="1" Grid.Column="1" Command="{Binding AddCommand}"></Button>
<CollectionView Grid.Row="2" Grid.ColumnSpan="2" ItemsSource="{Binding Items}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="{x:Type x:String}">
<SwipeView>
<SwipeView.RightItems>
<SwipeItem Text="Delete" BackgroundColor="Red"
Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:MainViewModel}}, Path=DeleteCommand}"
CommandParameter="{Binding .}">
</SwipeItem>
</SwipeView.RightItems>
<Grid Padding="0,5">
<Frame>
<Label Text="{Binding .}" FontSize="24"></Label>
</Frame>
</Grid>
</SwipeView>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</ContentPage>
View Model:
using System.Collections.ObjectModel;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
namespace MauiApp1.ViewModel
{
public partial class MainViewModel : ObservableObject
{
public MainViewModel()
{
Items = new();
Items.Add("test");
}
[ObservableProperty]
private ObservableCollection<string> items;
[ObservableProperty]
private string text;
[RelayCommand]
private void Add()
{
if (string.IsNullOrWhiteSpace(text))
{
return;
}
Items.Add(Text);
Text = string.Empty;
}
[RelayCommand]
private void Delete(string s)
{
if (Items.Contains(s))
{
Items.Remove(s);
}
}
}
}
Why is DeleteCommand not triggering?
try this
Command="{Binding BindingContext.DeleteCommand,
Source={x:Reference myPage}}"
where myPage is your page's name
<ContentPage x:Name="myPage" ...
Resolved,
I forgot to add <SwipeItems> element after <SwipeView.RightItems>.
AncestorType={x:Type viewmodel:MainViewModel}
Your viewmodel is not part of the visual tree, so you can't bind to it with relative source anyway.
You can use your CollectionView's Binding Context and then the specific property you need:
Command="{Binding BindingContext.DeleteCommand, Source={RelativeSource AncestorType={x:Type CollectionView}}}

Stumped on Xamarin databinding cast exception

I've followed examples and worked with XAML for WPF and this never happens so I'm totally confused about why Xamarin Forms is complaining.
Here's a simple form where I'm trying to use a ListView. The general structure is what was generated by Visual Studio but I've put in the ListView with an template for drawing two Labels:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PrivateDiary.Views.AboutPage"
xmlns:vm="clr-namespace:PrivateDiary.ViewModels"
Title="{Binding Title}">
<ContentPage.BindingContext>
<vm:AboutViewModel />
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<Color x:Key="Accent">#96d1ff</Color>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Orientation="Vertical">
<ListView x:Name="AboutListView"
ItemsSource="{Binding Items}"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<Grid VerticalOptions="Center" HorizontalOptions="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" Grid.Column="0" />
<Label Text="{Binding Detail}" Grid.Column="1" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
The code behind:
namespace PrivateDiary.Views
{
using Xamarin.Forms;
public partial class AboutPage : ContentPage
{
public AboutPage()
{
InitializeComponent();
}
}
}
and my View Model:
namespace PrivateDiary.ViewModels
{
using System.Collections.ObjectModel;
public class AboutViewModel : BaseViewModel
{
public ObservableCollection<AboutItem> Items { get; set; } = new ObservableCollection<AboutItem>();
public AboutViewModel()
{
Title = "About";
Items.Add(new AboutItem {Name = "Version", Detail = "0.3"});
Items.Add(new AboutItem {Name = "Privacy Policy", Detail = "#privacy"});
}
}
public class AboutItem
{
public string Name { get; set; }
public string Detail { get; set; }
}
}
BaseViewModel is the stock one generated by Visual Studio 2019 (16.10.3) so I won't list it here. It implements the details for INotifyPropertyChanged, a page Title property and IsBusy property.
When I run the app I get this:
If I removed the Items.Add(...) lines there's no problems.
Any ideas why it fails to cast?
Please add element ViewCell outside of element Grid in your xaml
You can refer to the following code:
<ContentPage.BindingContext>
<listviewapp1:AboutViewModel></listviewapp1:AboutViewModel>
</ContentPage.BindingContext>
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<ListView x:Name="AboutListView"
ItemsSource="{Binding Items}"
SelectionMode="None">
<ListView.ItemTemplate>
<DataTemplate>
<!--add ViewCell here-->
<ViewCell>
<Grid VerticalOptions="Center" HorizontalOptions="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" Grid.Column="0" />
<Label Text="{Binding Detail}" Grid.Column="1" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>

Stacklayout Inside Stackedlayout Binding IsVisible

I have a xaml view that is a simple listview which has a couple of stackedlayouts in the cells along with some simple binding of my model:
<?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:directory="clr-namespace:Directory;assembly=Directory"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:models="clr-namespace:Directory.Models"
xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin.Abstractions"
xmlns:viewModels="clr-namespace:Directory.ViewModels;assembly=Directory"
x:Class="Directory.Views.DirectoryList">
<ContentPage.BindingContext>
<viewModels:MasterViewModel/>
</ContentPage.BindingContext>
<ListView Margin="0,10"
ItemTapped="ListViewItem_Tabbed"
ItemsSource="{Binding PeopleCollectionGrouped}"
IsGroupingEnabled="True"
GroupDisplayBinding="{Binding Key}"
GroupShortNameBinding="{Binding Key}"
HasUnevenRows="True"
BackgroundColor="White">
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:People">
<ViewCell>
<Grid
Padding="10"
ColumnSpacing="10"
RowSpacing="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<controls:CircleImage
Aspect="AspectFill"
BorderColor="Black"
BorderThickness="3"
HeightRequest="66"
HorizontalOptions="CenterAndExpand"
Source="{Binding PhotoUrl}"
VerticalOptions="CenterAndExpand"
WidthRequest="66" />
<StackLayout Grid.Column="1" VerticalOptions="Center">
<Label Text="{Binding FullName}" />
<Label Text="{Binding Location}" />
<StackLayout IsVisible="{Binding IsVisible}"
Orientation="Horizontal"
Margin="0,0,80,0">
<Button Text="Place Order"
WidthRequest="110"
FontSize="15"
BackgroundColor="Chocolate"
TextColor="White"/>
</StackLayout>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
All the bindings work apart from the IsVisible binding which causes the app to crash with:
System.InvalidProgramException: Invalid IL code
If I change my Xaml so that the IsVisible property is not binded and just set to "True" then it compiles and loads.
I have no idea why this isn't working as the other values from the model are binded correctly.
Here is the People model, which "PeopleCollectionGrouped" is of:
public class People
{
[JsonProperty("photo_url")]
public string PhotoUrl { get; set; }
[JsonProperty("location")]
public string Location { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("first_name")]
public string FirstName { get; set; }
[JsonProperty("middle_name")]
public string MiddleName { get; set; }
[JsonProperty("last_name")]
public string LastName { get; set; }
public string FullName => $"{FirstName} {LastName}";
public string NameSort
{
get
{
if (string.IsNullOrWhiteSpace(FullName) || FullName.Length == 0)
{
return "?";
}
return FullName[0].ToString().ToUpper();
}
}
public bool IsVisible { get; set; }
}
If anyone can spot where i have gone wrong it would help