Listviews of Products and users

This commit is contained in:
2025-08-21 17:18:35 +02:00
parent 1649eaa992
commit 543b9c2aaf
13 changed files with 358 additions and 41 deletions

View File

@ -99,6 +99,9 @@
<MauiXaml Update="Views\ProductDetailView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Views\ProductListView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>
<MauiXaml Update="Views\UserDetailView.xaml">
<Generator>MSBuild:Compile</Generator>
</MauiXaml>

View File

@ -19,8 +19,8 @@
Route="UserListView" />
<ShellContent
Title="Products"
ContentTemplate="{DataTemplate views:ProductDetailView}"
Route="ProductDetailView" />
ContentTemplate="{DataTemplate views:ProductListView}"
Route="ProductListView" />
<ShellContent
Title="Customerss"
ContentTemplate="{DataTemplate views:CustomerDetailView}"

View File

@ -0,0 +1,26 @@
using AdventureWorks.EntityLayer;
using AdventureWorks.ViewModelLayer.ViewModelClasses;
using Common.Library;
namespace AdventureWorks.MAUI.CommandClasses
{
public class ProductViewModelCommands : ProductViewModel
{
#region Constructors
public ProductViewModelCommands() : base()
{
}
public ProductViewModelCommands(IRepository<Product> repo) : base(repo)
{
}
#endregion
public void LoadProducts()
{
Get();
}
public void LoadProductById(int id)
{
ProductObject = Get(id);
}
}
}

View File

@ -0,0 +1,53 @@
using AdventureWorks.EntityLayer;
using AdventureWorks.ViewModelLayer;
using Common.Library;
using System.Windows.Input;
namespace AdventureWorks.MAUI.CommandClasses;
public class UserViewModelCommands : UserViewModel
{
#region constructors
public UserViewModelCommands() : base()
{
}
public UserViewModelCommands(IRepository<User> repo) : base(repo)
{
}
public UserViewModelCommands(IRepository<User> repo, IRepository<PhoneType> phoneRepo) : base(repo, phoneRepo)
{
}
#endregion
#region Private Variables
private bool _IsSaveCommandEnabled = true;
#endregion
#region Public Properties
public bool IsSaveCommandEnabled
{
get { return _IsSaveCommandEnabled; }
set
{
_IsSaveCommandEnabled = value;
RaisePropertyChanged(nameof(IsSaveCommandEnabled));
}
}
#endregion
#region Commands
public ICommand SaveCommand { get; private set; }
#endregion
#region Init Method
public override void Init()
{
base.Init();
SaveCommand = new Command(() => Save(), () => IsSaveCommandEnabled);
}
#endregion
}

View File

@ -1,7 +1,7 @@
using AdventureWorks.DataLayer;
using AdventureWorks.EntityLayer;
using AdventureWorks.MAUI.CommandClasses;
using AdventureWorks.MAUI.Views;
using AdventureWorks.ViewModelLayer;
using Common.Library;
using Microsoft.Extensions.Logging;
@ -27,9 +27,17 @@ namespace AdventureWorks.MAUI
builder.Services.AddScoped<IRepository<User>, UserRepository>();
builder.Services.AddScoped<IRepository<EntityLayer.Color>, ColorRepository>();
builder.Services.AddScoped<IRepository<PhoneType>, PhoneTypeRepository>();
builder.Services.AddScoped<UserViewModel>();
builder.Services.AddScoped<UserViewModelCommands>();
builder.Services.AddScoped<UserDetailView>();
#if WINDOWS
builder.Services.AddScoped<UserListView>();
builder.Services.AddScoped<IRepository<Product>, ProductRepository>();
builder.Services.AddScoped<ProductViewModelCommands>();
builder.Services.AddScoped<ProductDetailView>();
builder.Services.AddScoped<ProductListView>();
#if XWINDOWS
SetWindowOptions(builder);
SetWindowHandlers();
#endif

View File

@ -0,0 +1,49 @@
<?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="AdventureWorks.MAUI.Views.ProductListView"
xmlns:partial="clr-namespace:AdventureWorks.MAUI.ViewsPartial"
xmlns:vm="clr-namespace:AdventureWorks.MAUI.CommandClasses"
xmlns:model="clr-namespace:AdventureWorks.EntityLayer;assembly=AdventureWorks.EntityLayer"
x:DataType="vm:ProductViewModelCommands"
Title="ProductListView">
<Border Style="{StaticResource Screen.Border}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<partial:HeaderView ViewTitle="Product List"
ViewDescription="The list of products in the system"/>
<CollectionView Grid.Row="1"
SelectionMode="Single"
ItemsSource="{Binding ProductList}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="model:Product">
<Border Margin="8" Padding="12" >
<VerticalStackLayout Spacing="4">
<HorizontalStackLayout>
<Label FontAttributes="Bold"
FontSize="Title"
Text="{Binding Name}" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="Color:" />
<Label Text="{Binding Color}" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="Price:" />
<Label Text="{Binding ListPrice, StringFormat='{0:C}'}" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Button Text="Edit" />
<Button Text="Delete" />
</HorizontalStackLayout>
</VerticalStackLayout>
</Border>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Grid>
</Border>
</ContentPage>

View File

@ -0,0 +1,24 @@
using AdventureWorks.MAUI.CommandClasses;
namespace AdventureWorks.MAUI.Views;
public partial class ProductListView : ContentPage
{
public ProductListView(ProductViewModelCommands viewModel)
{
InitializeComponent();
ViewModel = viewModel;
}
private readonly ProductViewModelCommands ViewModel;
protected override void OnAppearing()
{
base.OnAppearing();
BindingContext = ViewModel;
ViewModel.Get();
}
}

View File

@ -4,8 +4,8 @@
x:Class="AdventureWorks.MAUI.Views.UserDetailView"
xmlns:partial="clr-namespace:AdventureWorks.MAUI.ViewsPartial"
xmlns:converters="clr-namespace:AdventureWorks.MAUI.Converters"
xmlns:vm="clr-namespace:AdventureWorks.ViewModelLayer;assembly=AdventureWorks.ViewModelLayer"
x:DataType="vm:UserViewModel"
xmlns:vm="clr-namespace:AdventureWorks.MAUI.CommandClasses"
x:DataType="vm:UserViewModelCommands"
Title="User Information">
<ContentPage.Resources>
@ -53,18 +53,20 @@
Text="First Name" />
<Entry Grid.Row="2"
Grid.Column="1"
Text="{Binding UserObject.FirstName}"/>
Text="{Binding UserObject.FirstName}" />
<Label Grid.Row="3"
Text="Last Name" />
<Entry Grid.Row="3"
Grid.Column="1"
Text="{Binding UserObject.LastName}"/>
Text="{Binding UserObject.LastName}" />
<Label Grid.Row="4"
Text="Email Address" />
<Entry Grid.Row="4"
Grid.Column="1"
Text="{Binding UserObject.Email}"/>
<Label Grid.Row="5" Text="Is Enrolled ?"/>
Text="{Binding UserObject.Email}" />
<Label Grid.Row="5"
Text="Is Enrolled?" />
<FlexLayout Grid.Row="5"
Grid.Column="1"
@ -89,50 +91,51 @@
</FlexLayout>
<Label Grid.Row="6"
Text="Still Employed"/>
Text="Still Employed" />
<Switch Grid.Row="6"
Grid.Column="1"
IsToggled="{Binding UserObject.IsActive}"/>
<Label Text="Employee Type"
Grid.Row="7"/>
Grid.Row="7" />
<FlexLayout Grid.Row="7"
Grid.Column="1"
Wrap="Wrap"
Direction="Row">
<HorizontalStackLayout>
<Label Text="Full-Time"/>
<Label Text="Full-Time" />
<RadioButton x:Name="FullTime"
IsChecked="{Binding UserObject.IsFullTime}"
GroupName="EmployeeType"/>
GroupName="EmployeeType" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="Part-Time"/>
<RadioButton GroupName="EmployeeType" IsChecked="{Binding UserObject.IsFullTime, Converter={StaticResource invertedBoolean}}"/>
<Label Text="Part-Time" />
<RadioButton IsChecked="{Binding UserObject.IsFullTime, Converter={StaticResource invertedBoolean}}"
GroupName="EmployeeType" />
</HorizontalStackLayout>
</FlexLayout>
<Label Text="Birth Date"
Grid.Row="8"/>
Grid.Row="8" />
<DatePicker Grid.Row="8"
Grid.Column="1"
Date="{Binding UserObject.BirthDate}"
HorizontalOptions="Start"/>
HorizontalOptions="Start" />
<Label Text="Start Time"
Grid.Row="9"/>
Grid.Row="9" />
<TimePicker Grid.Row="9"
Grid.Column="1"
Time="{Binding UserObject.StartTime}"
IsEnabled="{Binding UserObject.IsFullTime, Converter={StaticResource invertedBoolean}}"/>
<Label Text="Phone"
Grid.Row="10"/>
Grid.Row="10" />
<FlexLayout Grid.Row="10"
Grid.Column="1"
Wrap="Wrap"
Direction="Row">
<HorizontalStackLayout>
<Entry MinimumWidthRequest="120"
Text="{Binding UserObject.Phone}"/>
Text="{Binding UserObject.Phone}" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Picker ItemsSource="{Binding PhoneTypesList}"
@ -146,7 +149,8 @@
<HorizontalStackLayout Grid.Row="12"
Grid.Column="1"
Spacing="5">
<Button Text="Save" Clicked="SaveButton_Clicked"/>
<Button Text="Save"
Command="{Binding SaveCommand}"/>
<Button Text="Cancel" />
</HorizontalStackLayout>
</Grid>

View File

@ -1,15 +1,16 @@
using AdventureWorks.ViewModelLayer;
using AdventureWorks.MAUI.CommandClasses;
namespace AdventureWorks.MAUI.Views;
public partial class UserDetailView : ContentPage
{
public UserDetailView(UserViewModel viewModel)
public UserDetailView(UserViewModelCommands viewModel)
{
InitializeComponent();
ViewModel = viewModel;
}
public UserViewModel ViewModel { get; set; }
public UserViewModelCommands ViewModel { get; set; }
protected override void OnAppearing()
{
@ -21,8 +22,5 @@ public partial class UserDetailView : ContentPage
ViewModel.Get(1); // Assuming you want to get the user with ID 1
}
private void SaveButton_Clicked(object sender, EventArgs e)
{
System.Diagnostics.Debugger.Break();
}
}

View File

@ -1,16 +1,49 @@
<?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"
xmlns:partial="clr-namespace:AdventureWorks.MAUI.ViewsPartial"
xmlns:vm="clr-namespace:AdventureWorks.MAUI.CommandClasses"
xmlns:model="clr-namespace:AdventureWorks.EntityLayer;assembly=AdventureWorks.EntityLayer"
x:Class="AdventureWorks.MAUI.Views.UserListView"
x:DataType="vm:UserViewModelCommands"
Title="User List">
<VerticalStackLayout VerticalOptions="Center"
HorizontalOptions="Center"
Spacing="10">
<Label
Text="User List"
FontSize="Header"
HorizontalOptions="Center" />
<Button Text="Navigate to Detali"
Clicked="NavigateToDetail_Clicked" />
<Border Style="{StaticResource Screen.Border}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<partial:HeaderView ViewTitle="User List"
ViewDescription="Use this Screen to view and manage users." />
<ListView Grid.Row="1"
ItemsSource="{Binding UserList}">
<ListView.ItemTemplate>
<DataTemplate x:DataType="model:User">
<ViewCell>
<Border Margin="8"
Padding="12">
<VerticalStackLayout Spacing="4">
<HorizontalStackLayout>
<Label FontAttributes="Bold"
FontSize="Title"
Text="{Binding LastNameFirstName}" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Label Text="Email" />
<Label Text="{Binding Email}" />
</HorizontalStackLayout>
<HorizontalStackLayout>
<Button Text="Edit" />
<Button Text="Delete" />
</HorizontalStackLayout>
</VerticalStackLayout>
</Border>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Border>
</ContentPage>

View File

@ -1,10 +1,22 @@
using AdventureWorks.MAUI.CommandClasses;
namespace AdventureWorks.MAUI.Views;
public partial class UserListView : ContentPage
{
public UserListView()
public UserListView(UserViewModelCommands viewModel)
{
InitializeComponent();
ViewModel = viewModel;
}
private readonly UserViewModelCommands ViewModel;
protected override void OnAppearing()
{
base.OnAppearing();
BindingContext = ViewModel;
ViewModel.Get();
}
private async void NavigateToDetail_Clicked(object sender, EventArgs e)

View File

@ -0,0 +1,91 @@
using AdventureWorks.EntityLayer;
using Common.Library;
using System.Collections.ObjectModel;
namespace AdventureWorks.ViewModelLayer.ViewModelClasses;
public class ProductViewModel : ViewModelBase
{
#region Constructors
public ProductViewModel() : base()
{
}
public ProductViewModel(IRepository<Product> repo) : base()
{
Repository = repo;
}
#endregion
#region Private Variables
private Product? _ProductObject = new();
private ObservableCollection<Product> _ProductList = new();
private readonly IRepository<Product>? Repository;
#endregion
#region Public Properties
public Product? ProductObject
{
get { return _ProductObject; }
set
{
_ProductObject = value;
RaisePropertyChanged(nameof(ProductObject));
}
}
public ObservableCollection<Product> ProductList
{
get { return _ProductList; }
set
{
_ProductList = value;
RaisePropertyChanged(nameof(ProductList));
}
}
#endregion
public ObservableCollection<Product> Get()
{
if (Repository != null)
{
ProductList = new ObservableCollection<Product>(Repository.Get());
}
return ProductList;
}
public Product Get(int id)
{
try
{
if (Repository != null)
{
ProductObject = Repository.Get(id);
}
else
{
ProductObject = new Product
{
ProductID = id,
Name = "A new product",
Color = "Black",
StandardCost = 10,
ListPrice = 20,
SellStartDate = Convert.ToDateTime("2020-10-15"),
Size = "LG"
};
}
}
catch (Exception)
{
throw;
}
return ProductObject;
}
public bool Save()
{
throw new NotImplementedException("Save method is not implemented yet.");
}
}

View File

@ -25,6 +25,7 @@ public class UserViewModel : ViewModelBase
#region Private Variables
private User? _UserObject = new();
private ObservableCollection<User> _UserList = new();
private readonly IRepository<User>? Repository;
private readonly IRepository<PhoneType>? _PhoneTypeRepository;
private ObservableCollection<string> _PhoneTypesList = new();
@ -43,6 +44,16 @@ public class UserViewModel : ViewModelBase
}
public ObservableCollection<User> UserList
{
get { return _UserList; }
set
{
_UserList = value;
RaisePropertyChanged(nameof(UserList));
}
}
public ObservableCollection<string> PhoneTypesList
{
get { return _PhoneTypesList; }
@ -59,6 +70,11 @@ public class UserViewModel : ViewModelBase
#region Get Method
public ObservableCollection<User> Get()
{
if (Repository != null)
{
UserList = new ObservableCollection<User>(Repository.Get());
}
return new();
}