main
syneffort 1 year ago
parent fe03da6100
commit ee22a4de50
  1. 7
      MyFirstMauiApp/UseRestService/AppShell.xaml
  2. 6
      MyFirstMauiApp/UseRestService/AppShell.xaml.cs
  3. 79
      MyFirstMauiApp/UseRestService/Data/PartManager.cs
  4. 26
      MyFirstMauiApp/UseRestService/Pages/AddPartPage.xaml
  5. 35
      MyFirstMauiApp/UseRestService/Pages/AddPartPage.xaml.cs
  6. 34
      MyFirstMauiApp/UseRestService/Pages/PartsPage.xaml
  7. 3
      MyFirstMauiApp/UseRestService/Pages/PartsPage.xaml.cs
  8. 3
      MyFirstMauiApp/UseRestService/UseRestService.csproj
  9. 89
      MyFirstMauiApp/UseRestService/ViewModels/AddPartViewModel.cs
  10. 81
      MyFirstMauiApp/UseRestService/ViewModels/PartsViewModel.cs

@ -3,12 +3,11 @@
x:Class="UseRestService.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:UseRestService"
xmlns:local="clr-namespace:UseRestService.Pages"
Shell.FlyoutBehavior="Disabled">
<ShellContent
Title="Home"
ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage" />
ContentTemplate="{DataTemplate local:PartsPage}"
Route="listparts" />
</Shell>

@ -1,10 +1,14 @@
namespace UseRestService
using UseRestService.Pages;
namespace UseRestService
{
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
Routing.RegisterRoute("addpart", typeof(AddPartPage));
}
}
}

@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Json;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace UseRestService.Data
@ -9,34 +11,99 @@ namespace UseRestService.Data
public static class PartsManager
{
// TODO: Add fields for BaseAddress, Url, and authorizationKey
static readonly string BaseAddress = "URL GOES HERE";
static readonly string BaseAddress = "https://mslearnpartsserver425916999.azurewebsites.net";
static readonly string Url = $"{BaseAddress}/api/";
static HttpClient client;
static string authorizationKey;
private static async Task<HttpClient> GetClient()
{
throw new NotImplementedException();
if (client != null)
return client;
client = new HttpClient();
if (string.IsNullOrEmpty(authorizationKey))
{
authorizationKey = await client.GetStringAsync($"{Url}login");
authorizationKey = JsonSerializer.Deserialize<string>(authorizationKey);
}
client.DefaultRequestHeaders.Add("Authorization", authorizationKey);
client.DefaultRequestHeaders.Add("Accept", "application/json");
return client;
}
public static async Task<IEnumerable<Part>> GetAll()
{
throw new NotImplementedException();
if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet)
return new List<Part>();
var client = await GetClient();
string result = await client.GetStringAsync($"{Url}parts");
return JsonSerializer.Deserialize<List<Part>>(result, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
});
}
public static async Task<Part> Add(string partName, string supplier, string partType)
{
throw new NotImplementedException();
if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet)
return new Part();
var part = new Part()
{
PartName = partName,
Suppliers = new List<string>(new[] { supplier }),
PartID = string.Empty,
PartType = partType,
PartAvailableDate = DateTime.Now.Date
};
var msg = new HttpRequestMessage(HttpMethod.Post, $"{Url}parts");
msg.Content = JsonContent.Create<Part>(part);
var response = await client.SendAsync(msg);
response.EnsureSuccessStatusCode();
var returnedJson = await response.Content.ReadAsStringAsync();
var insertedPart = JsonSerializer.Deserialize<Part>(returnedJson, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
});
return insertedPart;
}
public static async Task Update(Part part)
{
throw new NotImplementedException();
if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet)
return;
HttpRequestMessage msg = new(HttpMethod.Put, $"{Url}parts/{part.PartID}");
msg.Content = JsonContent.Create<Part>(part);
var client = await GetClient();
var response = await client.SendAsync(msg);
response.EnsureSuccessStatusCode();
}
public static async Task Delete(string partID)
{
throw new NotImplementedException();
if (Connectivity.Current.NetworkAccess != NetworkAccess.Internet)
return;
HttpRequestMessage msg = new(HttpMethod.Delete, $"{Url}parts/{partID}");
var client = await GetClient();
var response = await client.SendAsync(msg);
response.EnsureSuccessStatusCode();
}
}
}

@ -0,0 +1,26 @@
<?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="UseRestService.Pages.AddPartPage"
xmlns:viewmodel="clr-namespace:UseRestService.ViewModels"
x:DataType="viewmodel:AddPartViewModel"
Title="Edit Part">
<Grid RowDefinitions="*,Auto" ColumnDefinitions="*,*,*" ColumnSpacing="5" Padding="10">
<TableView Intent="Data" Grid.Row="0" Grid.ColumnSpan="3">
<TableRoot>
<TableSection Title="Part Info">
<EntryCell Label="Part ID" Text="{Binding PartID}" IsEnabled="False" />
<EntryCell Label="Part Name" Text="{Binding PartName}" />
<EntryCell Label="Part Type" Text="{Binding PartType}" />
<EntryCell Label="Supplier" Text="{Binding Suppliers}" />
</TableSection>
</TableRoot>
</TableView>
<Button Text="Save" Grid.Row="1" Grid.Column="0" Command="{Binding SaveDataCommand}" Margin="20,0"/>
<Button Text="Delete" Grid.Row="1" Grid.Column="1" Command="{Binding DeletePartCommand}"/>
<Button Text="Cancel" Grid.Row="1" Grid.Column="2" Command="{Binding DoneEditingCommand}" Margin="20,0"/>
</Grid>
</ContentPage>

@ -0,0 +1,35 @@
using UseRestService.Data;
using UseRestService.ViewModels;
namespace UseRestService.Pages;
[QueryProperty("PartToDisplay", "part")]
public partial class AddPartPage : ContentPage
{
AddPartViewModel viewModel;
public AddPartPage()
{
InitializeComponent();
viewModel = new AddPartViewModel();
BindingContext = viewModel;
}
Part _partToDisplay;
public Part PartToDisplay
{
get => _partToDisplay;
set
{
if (_partToDisplay == value)
return;
_partToDisplay = value;
viewModel.PartID = _partToDisplay.PartID;
viewModel.PartName = _partToDisplay.PartName;
viewModel.Suppliers = _partToDisplay.SupplierString;
viewModel.PartType = _partToDisplay.PartType;
}
}
}

@ -2,11 +2,33 @@
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="UseRestService.Pages.PartsPage"
Title="PartsPage">
<VerticalStackLayout>
<Label
Text="Welcome to .NET MAUI!"
VerticalOptions="Center"
HorizontalOptions="Center" />
Title="Part List"
xmlns:viewModel="clr-namespace:UseRestService.ViewModels"
xmlns:data="clr-namespace:UseRestService.Data"
x:DataType="viewModel:PartsViewModel">
<Grid RowDefinitions="Auto,*" ColumnDefinitions="*">
<Button Grid.Row="0" Grid.Column="0" Text="Add New Part" Margin="20, 10, 20, 10" Command="{Binding AddNewPartCommand}"/>
<RefreshView Grid.Row="1" Grid.Column="0" IsRefreshing="{Binding IsRefreshing}" x:Name="refreshView"
Command="{Binding LoadDataCommand}">
<CollectionView Margin="30,20,30,30"
ItemsSource="{Binding Parts}"
SelectedItem="{Binding SelectedPart, Mode=TwoWay}"
SelectionChangedCommand="{Binding PartSelectedCommand}"
SelectionMode="Single">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Vertical" ItemSpacing="20" />
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="data:Part">
<VerticalStackLayout Padding="15,10" Margin="10,5,10,5">
<Label Text="{Binding PartID, StringFormat='ID: {0}'}" FontSize="Title" Margin="0,0,0,20"/>
<Label Text="{Binding PartName, StringFormat='Part Name: {0}'}"/>
<Label Text="{Binding PartType, StringFormat='Part Type: {0}'}"/>
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</RefreshView>
</Grid>
</ContentPage>

@ -1,3 +1,5 @@
using UseRestService.ViewModels;
namespace UseRestService.Pages;
public partial class PartsPage : ContentPage
@ -5,5 +7,6 @@ public partial class PartsPage : ContentPage
public PartsPage()
{
InitializeComponent();
BindingContext = new PartsViewModel();
}
}

@ -54,6 +54,9 @@
</ItemGroup>
<ItemGroup>
<MauiXaml Update="Pages\AddPartPage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Pages\PartsPage.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>

@ -0,0 +1,89 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UseRestService.Data;
namespace UseRestService.ViewModels
{
public partial class AddPartViewModel : ObservableObject
{
[ObservableProperty]
string _partID;
[ObservableProperty]
string _partName;
[ObservableProperty]
string _suppliers;
[ObservableProperty]
string _partType;
public AddPartViewModel()
{
}
[RelayCommand]
async Task SaveData()
{
if (string.IsNullOrWhiteSpace(PartID))
await InsertPart();
else
await UpdatePart();
}
[RelayCommand]
async Task InsertPart()
{
await PartsManager.Add(PartName, Suppliers, PartType);
WeakReferenceMessenger.Default.Send(new RefreshMessage(true));
await Shell.Current.GoToAsync("..");
}
[RelayCommand]
async Task UpdatePart()
{
Part partToSave = new()
{
PartID = PartID,
PartName = PartName,
PartType = PartType,
Suppliers = Suppliers.Split(",").ToList()
};
await PartsManager.Update(partToSave);
WeakReferenceMessenger.Default.Send(new RefreshMessage(true));
await Shell.Current.GoToAsync("..");
}
[RelayCommand]
async Task DeletePart()
{
if (string.IsNullOrWhiteSpace(PartID))
return;
await PartsManager.Delete(PartID);
WeakReferenceMessenger.Default.Send(new RefreshMessage(true));
await Shell.Current.GoToAsync("..");
}
[RelayCommand]
async Task DoneEditing()
{
await Shell.Current.GoToAsync("..");
}
}
}

@ -1,13 +1,92 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Messaging;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UseRestService.Data;
namespace UseRestService.ViewModels
{
internal class PartsViewModel : ObservableObject
internal partial class PartsViewModel : ObservableObject
{
[ObservableProperty]
ObservableCollection<Part> _parts;
[ObservableProperty]
bool _isRefreshing = false;
[ObservableProperty]
bool _isBusy = false;
[ObservableProperty]
Part _selectedPart;
public PartsViewModel()
{
_parts = new ObservableCollection<Part>();
WeakReferenceMessenger.Default.Register<RefreshMessage>(this, async (r, m) =>
{
await LoadData();
});
Task.Run(LoadData);
}
[RelayCommand]
async Task PartSelected()
{
if (SelectedPart == null)
return;
var navigationParameter = new Dictionary<string, object>()
{
{ "part", SelectedPart }
};
await Shell.Current.GoToAsync("addpart", navigationParameter);
MainThread.BeginInvokeOnMainThread(() => SelectedPart = null);
}
[RelayCommand]
async Task LoadData()
{
if (IsBusy)
return;
try
{
IsRefreshing = true;
IsBusy = true;
var partsCollection = await PartsManager.GetAll();
MainThread.BeginInvokeOnMainThread(() =>
{
Parts.Clear();
foreach (Part part in partsCollection)
{
Parts.Add(part);
}
});
}
finally
{
IsRefreshing = false;
IsBusy = false;
}
}
[RelayCommand]
async Task AddNewPart()
{
await Shell.Current.GoToAsync("addpart");
}
}
}

Loading…
Cancel
Save