Adding NavigationView

This commit is contained in:
Selim Mustafaev 2023-10-29 22:14:54 +03:00
parent c7038a5ed9
commit 6d85cf53c9
22 changed files with 255 additions and 50 deletions

View File

@ -1,14 +1,14 @@
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AutoCat"
xmlns:sty="using:FluentAvalonia.Styling"
x:Class="AutoCat.App"
RequestedThemeVariant="Default">
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<!--
<FluentTheme/>
-->
<sty:FluentAvaloniaTheme />
</Application.Styles>
</Application>

View File

@ -3,7 +3,7 @@ using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using AutoCat.ViewModels;
using AutoCat.Views;
using AutoCat.Windows;
using AutoCatCore.Services.Api;
using AutoCatCore.Services.Storage;
using Microsoft.Extensions.DependencyInjection;
@ -18,10 +18,11 @@ public partial class App : Application
private static void RegisterDependencies(HostBuilderContext context, IServiceCollection services)
{
// Services
services.AddSingleton<IApiService, ApiService>();
services.AddSingleton<IStorageService, StorageService>();
services.AddSingleton<IApiService, ApiService>();
// ViewModels
services.AddTransient<HistoryListViewModel>();
services.AddTransient<AuthWindowViewModel>();
services.AddTransient<MainWindowViewModel>();

View File

@ -23,6 +23,7 @@
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics" Version="11.0.5" />
<PackageReference Include="Avalonia.ReactiveUI" Version="11.0.5" />
<PackageReference Include="Avalonia.Themes.Fluent" Version="11.0.5" />
<PackageReference Include="FluentAvaloniaUI" Version="2.0.4" />
<PackageReference Include="MessageBox.Avalonia" Version="3.1.4" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />

View File

@ -0,0 +1,30 @@
using System.Collections.ObjectModel;
using AutoCat.ViewModels;
using AutoCatCore.Model;
namespace AutoCat.Mocks;
public class HistoryListViewModelMock: ViewModelBase
{
public ObservableCollection<Vehicle> Vehicles { get; set; }
public HistoryListViewModelMock()
{
var vehicle1 = new Vehicle
{
Number = "А007АА761"
};
var vehicle2 = new Vehicle
{
Number = "А008АА761"
};
var vehicle3 = new Vehicle
{
Number = "А009АА761"
};
Vehicles = new ObservableCollection<Vehicle> { vehicle1, vehicle2, vehicle3 };
}
}

View File

@ -0,0 +1,32 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:utils="using:AutoCat.Utils"
xmlns:vm="using:AutoCat.ViewModels"
xmlns:mocks="using:AutoCat.Mocks"
mc:Ignorable="d" d:DesignWidth="350" d:DesignHeight="550"
x:Class="AutoCat.Pages.HistoryListPage"
x:DataType="vm:HistoryListViewModel"
x:CompileBindings="True"
DataContext="{utils:ViewModelProvider vm:HistoryListViewModel}"
Design.DataContext="mocks:HistoryListViewModelMock">
<ListBox ItemsSource="{Binding Vehicles}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<Grid ColumnDefinitions="*">
<TextBlock Text="{Binding Brand.Name.Original}"/>
</Grid>
<Grid ColumnDefinitions="* Auto" RowDefinitions="* *">
<TextBlock Grid.RowSpan="2" Text="{Binding Number}"/>
<TextBlock Grid.Column="1" Grid.Row="0" Text="{Binding UpdatedDate}"/>
<TextBlock Grid.Column="1" Grid.Row="1" Text="{Binding AddedDate}"/>
</Grid>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</UserControl>

View File

@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace AutoCat.Pages;
public partial class HistoryListPage : UserControl
{
public HistoryListPage()
{
InitializeComponent();
}
}

View File

@ -0,0 +1,13 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:pages="clr-namespace:AutoCat.Pages"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AutoCat.Pages.HistoryPage">
<Grid ColumnDefinitions="300, Auto, *">
<pages:HistoryListPage/>
<GridSplitter Grid.Column="1" ResizeDirection="Columns"/>
<pages:ReportPage Grid.Column="2"/>
</Grid>
</UserControl>

View File

@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace AutoCat.Pages;
public partial class HistoryPage : UserControl
{
public HistoryPage()
{
InitializeComponent();
}
}

View File

@ -0,0 +1,8 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AutoCat.Pages.ReportPage">
Welcome to Avalonia!
</UserControl>

View File

@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace AutoCat.Pages;
public partial class ReportPage : UserControl
{
public ReportPage()
{
InitializeComponent();
}
}

View File

@ -0,0 +1,8 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AutoCat.Pages.SettingsPage">
Settings Page
</UserControl>

View File

@ -0,0 +1,13 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace AutoCat.Pages;
public partial class SettingsPage : UserControl
{
public SettingsPage()
{
InitializeComponent();
}
}

View File

@ -1,27 +0,0 @@
using System;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using AutoCat.ViewModels;
namespace AutoCat;
public class ViewLocator : IDataTemplate
{
public Control Build(object data)
{
var name = data.GetType().FullName!.Replace("ViewModel", "View");
var type = Type.GetType(name);
if (type != null)
{
return (Control)Activator.CreateInstance(type)!;
}
return new TextBlock { Text = "Not Found: " + name };
}
public bool Match(object data)
{
return data is ViewModelBase;
}
}

View File

@ -0,0 +1,46 @@
using System;
using System.Collections.ObjectModel;
using System.Threading.Tasks;
using AutoCatCore.Model;
using AutoCatCore.Services.Api;
using DynamicData;
namespace AutoCat.ViewModels;
public class HistoryListViewModel: ViewModelBase
{
#region Dependencies
private readonly IApiService _apiService;
#endregion
#region Properties
public ObservableCollection<Vehicle> Vehicles { get; set; }
#endregion
public HistoryListViewModel(IApiService apiService)
{
_apiService = apiService;
Vehicles = new ObservableCollection<Vehicle>();
LoadVehicles();
}
private async Task LoadVehicles()
{
try
{
var pagedResponse = await _apiService.GetVehicles();
Vehicles.Clear();
Vehicles.AddRange(pagedResponse.Items);
Console.WriteLine($"Loaded vehicles: {Vehicles.Count}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}

View File

@ -1,11 +0,0 @@
using Avalonia.Controls;
namespace AutoCat.Views;
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}

View File

@ -7,7 +7,7 @@
xmlns:mocks="using:AutoCat.Mocks"
xmlns:ext="using:AutoCat.Extensions"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AutoCat.Views.AuthWindow"
x:Class="AutoCat.Windows.AuthWindow"
x:DataType="vm:AuthWindowViewModel"
Title="AuthWindow"
Width="800" Height="600"

View File

@ -5,7 +5,7 @@ using Avalonia.Controls.ApplicationLifetimes;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting.Internal;
namespace AutoCat.Views;
namespace AutoCat.Windows;
public partial class AuthWindow : Window
{

View File

@ -3,13 +3,17 @@
xmlns:vm="using:AutoCat.ViewModels"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:utils="using:AutoCat.Utils"
xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:uip="using:FluentAvalonia.UI.Controls.Primitives"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
Width="800"
Height="600"
x:Class="AutoCat.Views.MainWindow"
x:Class="AutoCat.Windows.MainWindow"
x:DataType="vm:MainWindowViewModel"
Icon="/Assets/avalonia-logo.ico"
Title="AutoCat">
Title="AutoCat"
DataContext="{utils:ViewModelProvider vm:MainWindowViewModel}">
<Design.DataContext>
<!-- This only sets the DataContext for the previewer in an IDE,
@ -17,6 +21,15 @@
<vm:MainWindowViewModel/>
</Design.DataContext>
<TextBlock Text="{Binding Greeting}" HorizontalAlignment="Center" VerticalAlignment="Center"/>
<Grid>
<ui:NavigationView x:Name="NavView"
PaneDisplayMode="Left"
IsPaneOpen="false"
OpenPaneLength="180">
<ui:NavigationView.MenuItems>
<ui:NavigationViewItem Content="History" Tag="HistoryPage" IconSource="Clock"/>
</ui:NavigationView.MenuItems>
</ui:NavigationView>
</Grid>
</Window>

View File

@ -0,0 +1,33 @@
using System;
using System.Linq;
using AutoCat.Pages;
using Avalonia.Controls;
using FluentAvalonia.UI.Controls;
namespace AutoCat.Windows;
public partial class MainWindow : Window
{
private readonly SettingsPage _settingsPage = new SettingsPage();
private readonly HistoryPage _historyPage = new HistoryPage();
public MainWindow()
{
InitializeComponent();
NavView.SelectionChanged += NavSelectionChanged;
NavView.SelectedItem = NavView.MenuItems.First();
}
private void NavSelectionChanged(object? sender, NavigationViewSelectionChangedEventArgs args)
{
if (args.IsSettingsSelected)
{
NavView.Content = _settingsPage;
}
else
{
NavView.Content = _historyPage;
}
}
}

View File

@ -3,6 +3,7 @@ using System.Text.Json;
using AutoCat.Model.Requests;
using AutoCatCore.Model;
using AutoCatCore.Model.Requests;
using AutoCatCore.Services.Storage;
namespace AutoCatCore.Services.Api;
@ -10,10 +11,11 @@ public class ApiService : IApiService
{
private readonly HttpClient _httpClient;
public ApiService()
public ApiService(IStorageService storageService)
{
_httpClient = new HttpClient();
_httpClient.BaseAddress = new Uri("https://vps.aliencat.pro:8443");
SetAccessToken(storageService.AuthToken);
}
private static T GetDataOrThrow<T>(string response)

View File

@ -6,5 +6,7 @@ public interface IStorageService
{
public bool IsLoggedIn { get; }
public string? AuthToken { get; }
public Task SetUser(User user);
}

View File

@ -18,6 +18,8 @@ public class StorageService: IStorageService
}
}
public string? AuthToken => _dbContext.Users.Any() ? _dbContext.Users.First().Token : null;
public async Task SetUser(User user)
{
await _dbContext.Users.ExecuteDeleteAsync();