Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions WpfApp.sln
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33516.290
# Visual Studio Version 18
VisualStudioVersion = 18.4.11626.88 stable
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WpfApp", "WpfApp\WpfApp.csproj", "{E29065B9-9FFC-4D05-8B0B-FB1B8EB440A4}"
EndProject
Expand Down
8 changes: 8 additions & 0 deletions WpfApp/Abstractions/IStickyHeaderSupport.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Leosac.WpfApp.Abstractions
{
public interface IStickyHeaderSupport
{
bool SupportsStickyHeader { get; }
bool IsStickyHeaderVisible { get; }
}
}
12 changes: 5 additions & 7 deletions WpfApp/Domain/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
using MaterialDesignThemes.Wpf;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Leosac.SharedServices;
using MaterialDesignThemes.Wpf;
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Leosac.SharedServices;
using System.Windows.Controls;

namespace Leosac.WpfApp.Domain
{
public class MainWindowViewModel : ObservableObject
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod()?.DeclaringType);

Check warning on line 14 in WpfApp/Domain/MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 6.0.x)

Possible null reference argument for parameter 'type' in 'ILog LogManager.GetLogger(Type type)'.

Check warning on line 14 in WpfApp/Domain/MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 6.0.x)

Possible null reference argument for parameter 'type' in 'ILog LogManager.GetLogger(Type type)'.

Check warning on line 14 in WpfApp/Domain/MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 6.0.x)

Possible null reference argument for parameter 'type' in 'ILog LogManager.GetLogger(Type type)'.

Check warning on line 14 in WpfApp/Domain/MainWindowViewModel.cs

View workflow job for this annotation

GitHub Actions / build (windows-latest, 6.0.x)

Possible null reference argument for parameter 'type' in 'ILog LogManager.GetLogger(Type type)'.

public MainWindowViewModel(ISnackbarMessageQueue snackbarMessageQueue)
{
Expand Down
18 changes: 11 additions & 7 deletions WpfApp/Domain/NavItem.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System;
using System.Windows.Controls;
using CommunityToolkit.Mvvm.ComponentModel;
using Leosac.WpfApp.Abstractions;
using System;
using System.Windows;
using CommunityToolkit.Mvvm.ComponentModel;
using System.Windows.Controls;

namespace Leosac.WpfApp.Domain
{
Expand All @@ -23,6 +24,7 @@ public NavItem(string name, Type contentType, string icon, object? dataContext)
_contentType = contentType;
Icon = icon;
_dataContext = dataContext;
_stickyHeaderSupport = dataContext as IStickyHeaderSupport;
}

public string Name { get; }
Expand All @@ -31,10 +33,12 @@ public NavItem(string name, Type contentType, string icon, object? dataContext)

public object? Content => _content ??= CreateContent();

public object? DataContext
{
get => _dataContext;
}
public object? DataContext => _dataContext;

private readonly IStickyHeaderSupport? _stickyHeaderSupport;
public IStickyHeaderSupport? StickyHeaderSupport => _stickyHeaderSupport;

public object? StickyHeader { get; set; }

public ScrollBarVisibility HorizontalScrollBarVisibilityRequirement
{
Expand Down
11 changes: 11 additions & 0 deletions WpfApp/Domain/StickyHeaderSupportBase.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using Leosac.WpfApp.Abstractions;
using CommunityToolkit.Mvvm.ComponentModel;

namespace Leosac.WpfApp.Domain
{
public abstract class StickyHeaderSupportBase : ObservableObject, IStickyHeaderSupport
{
public virtual bool SupportsStickyHeader => false;
public virtual bool IsStickyHeaderVisible => false;
}
}
16 changes: 8 additions & 8 deletions WpfApp/LeosacWinAppInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,20 @@ namespace Leosac.WpfApp
{
public abstract class LeosacWinAppInfo : LeosacAppInfo
{
public static LeosacWinAppInfo? WinInstance
{
get => Instance as LeosacWinAppInfo;
}
private const string DefaultApplicationLogoPath = "/WpfApp;component/images/leosac.png";

public static LeosacWinAppInfo? WinInstance => Instance as LeosacWinAppInfo;

public string ApplicationLogo { get; protected set; }

public RelayCommand? SettingsCommand { get; protected set; }

protected LeosacWinAppInfo()
{
ApplicationLogo = "/WpfApp;component/images/leosac.png";
ApplicationLogo = DefaultApplicationLogoPath;
SettingsCommand = null;
}

public string ApplicationLogo { get; protected set; }

public RelayCommand? SettingsCommand { get; protected set; }

public abstract void InitializeMainWindow(MainWindowViewModel model);

Expand Down
117 changes: 69 additions & 48 deletions WpfApp/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
TextElement.Foreground="{DynamicResource MaterialDesign.Brush.Foreground}"
TextElement.FontWeight="Regular"
TextElement.FontSize="13"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextRenderingMode="Auto"
TextOptions.TextFormattingMode="Ideal"
TextOptions.TextRenderingMode="Auto"
Background="{DynamicResource MaterialDesign.Brush.Background}"
FontFamily="{DynamicResource MaterialDesignFont}" Loaded="Window_Loaded">
<Window.Resources>
Expand Down Expand Up @@ -72,34 +72,42 @@
<ColumnDefinition Width="64" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<materialDesign:PackIcon Grid.Row="0" Grid.Column="0" Kind="{Binding Icon}" Height="32" Width="64" Padding="3,3,3,3" />
<TextBlock Grid.Row="0" Grid.Column="1" AutomationProperties.AutomationId="NavItemPage" Text="{Binding Name}" Padding="3,3,3,3" VerticalAlignment="Center" />
<materialDesign:PackIcon Grid.Column="0" Kind="{Binding Icon}" Width="64" Height="32" Padding="3"/>
<TextBlock Grid.Column="1" AutomationProperties.AutomationId="NavItemPage" Text="{Binding Name}" Padding="3" VerticalAlignment="Center"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</DockPanel>
</materialDesign:DrawerHost.LeftDrawerContent>

<DockPanel>
<materialDesign:ColorZone Padding="16"
materialDesign:ElevationAssist.Elevation="Dp4"
DockPanel.Dock="Top"
Mode="PrimaryMid">
<DockPanel>
<StackPanel Orientation="Horizontal">
materialDesign:ElevationAssist.Elevation="Dp4"
DockPanel.Dock="Top"
Mode="PrimaryMid">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Orientation="Horizontal">
<ToggleButton x:Name="MenuToggleButton"
AutomationProperties.Name="HamburgerToggleButton"
IsChecked="False"
Style="{StaticResource MaterialDesignHamburgerToggleButton}" />
AutomationProperties.Name="HamburgerToggleButton"
IsChecked="False"
Style="{StaticResource MaterialDesignHamburgerToggleButton}" />
<Image Margin="16,0,0,0" Source="{Binding Source={x:Static local:LeosacWinAppInfo.WinInstance}, Path=ApplicationLogo}" Height="75"/>
</StackPanel>

<materialDesign:PopupBox DockPanel.Dock="Right"
PlacementMode="BottomAndAlignRightEdges"
StaysOpen="False">
<TextBlock Grid.Column="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="22"
TextTrimming="CharacterEllipsis"
AutomationProperties.Name="{Binding Source={x:Static local:LeosacWinAppInfo.WinInstance}, Path=ApplicationTitle}"
Text="{Binding Source={x:Static local:LeosacWinAppInfo.WinInstance}, Path=ApplicationTitle}" />
<materialDesign:PopupBox Grid.Column="2"
PlacementMode="BottomAndAlignRightEdges"
StaysOpen="False">

<StackPanel>
<Grid Margin="10">
Expand All @@ -108,12 +116,16 @@
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Margin="0,0,10,0" Text="{x:Static properties:Resources.LightMode}" />
<ToggleButton Grid.Column="1" IsChecked="{Binding IsDarkMode}" />
<TextBlock Grid.Column="2" Margin="10,0,0,0" Text="{x:Static properties:Resources.DarkMode}" />

<TextBlock Margin="0,0,10,0"
Text="{x:Static properties:Resources.LightMode}" />

<ToggleButton Grid.Column="1"
IsChecked="{Binding IsDarkMode}" />

<TextBlock Grid.Column="2"
Margin="10,0,0,0"
Text="{x:Static properties:Resources.DarkMode}" />
</Grid>

<Separator />
Expand All @@ -123,18 +135,8 @@
<Button Content="{x:Static properties:Resources.About}" Command="{Binding Path=OpenAboutCommand}" />
</StackPanel>
</materialDesign:PopupBox>

<Image Margin="16,0,0,0" Source="{Binding Source={x:Static local:LeosacWinAppInfo.WinInstance}, Path=ApplicationLogo}" Height="75" />

<TextBlock Margin="-152,0,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Center"
AutomationProperties.Name="{Binding Source={x:Static local:LeosacWinAppInfo.WinInstance}, Path=ApplicationTitle}"
FontSize="22"
Text="{Binding Source={x:Static local:LeosacWinAppInfo.WinInstance}, Path=ApplicationTitle}" />
</DockPanel>
</Grid>
</materialDesign:ColorZone>

<materialDesign:ColorZone DockPanel.Dock="Bottom" Padding="20" materialDesign:ElevationAssist.Elevation="Dp4" ClipToBounds="False" CornerRadius="15,15,0,0" Mode="PrimaryLight"
Visibility="{Binding ShowPlanFooter, Converter={StaticResource BooleanToVisibilityConverter}}">
<Grid>
Expand All @@ -161,17 +163,36 @@
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<ScrollViewer x:Name="MainScrollViewer"
Grid.Row="1"
materialDesign:ScrollViewerAssist.IsAutoHideEnabled="True"
HorizontalScrollBarVisibility="{Binding SelectedItem.HorizontalScrollBarVisibilityRequirement, FallbackValue=Disabled}"
VerticalScrollBarVisibility="{Binding SelectedItem.VerticalScrollBarVisibilityRequirement, FallbackValue=Disabled}">
<ContentControl Margin="{Binding MarginRequirement, FallbackValue=16}"
Content="{Binding Content, UpdateSourceTrigger=PropertyChanged, FallbackValue={x:Null}}"
DataContext="{Binding SelectedItem}"
DataContextChanged="OnSelectedMenuItemChanged" >
<Grid Grid.Row="1">
<ScrollViewer x:Name="MainScrollViewer"
materialDesign:ScrollViewerAssist.IsAutoHideEnabled="True"
HorizontalScrollBarVisibility="{Binding SelectedItem.HorizontalScrollBarVisibilityRequirement, FallbackValue=Disabled}"
VerticalScrollBarVisibility="{Binding SelectedItem.VerticalScrollBarVisibilityRequirement, FallbackValue=Disabled}">

<ContentControl Margin="{Binding MarginRequirement, FallbackValue=16}"
Content="{Binding Content, UpdateSourceTrigger=PropertyChanged, FallbackValue={x:Null}}"
DataContext="{Binding SelectedItem}"
DataContextChanged="OnSelectedMenuItemChanged" />
</ScrollViewer>
<ContentControl Content="{Binding SelectedItem.StickyHeader}"
VerticalAlignment="Top"
HorizontalAlignment="Stretch" Panel.ZIndex="999" Margin="0,0,16,0">
<ContentControl.Style>
<Style TargetType="ContentControl">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding SelectedItem.StickyHeaderSupport.SupportsStickyHeader, TargetNullValue=False, FallbackValue=False}" Value="True"/>
<Condition Binding="{Binding SelectedItem.StickyHeaderSupport.IsStickyHeaderVisible, TargetNullValue=False, FallbackValue=False}" Value="True"/>
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Visible"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
</ContentControl>
</ScrollViewer>
</Grid>

<materialDesign:Snackbar x:Name="MainSnackbar"
Grid.Row="1"
Expand All @@ -181,4 +202,4 @@
</DockPanel>
</materialDesign:DrawerHost>
</materialDesign:DialogHost>
</Window>
</Window>
7 changes: 5 additions & 2 deletions WpfApp/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Leosac.WpfApp.Domain;
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls.Primitives;
Expand All @@ -15,10 +16,12 @@ public partial class MainWindow : Window
public MainWindow()
{
InitializeComponent();

DataContext = new MainWindowViewModel(MainSnackbar.MessageQueue!);
if (MainSnackbar.MessageQueue is null)
throw new InvalidOperationException("Snackbar queue not initialized.");
DataContext = new MainWindowViewModel(MainSnackbar.MessageQueue);
}


private void OnSelectedMenuItemChanged(object sender, DependencyPropertyChangedEventArgs e)
=> MainScrollViewer.ScrollToHome();

Expand Down
4 changes: 2 additions & 2 deletions WpfApp/SnackbarHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public static void EnqueueError(ISnackbarMessageQueue? queue, Exception? ex, str
var errorIcon = new PackIcon() { Kind = PackIconKind.ExclamationThick };
DockPanel.SetDock(errorIcon, Dock.Left);
panel.Children.Add(errorIcon);
panel.Children.Add(new TextBlock() { Text = message, Margin = new Thickness(5, 0, 0 ,0), TextWrapping = TextWrapping.Wrap });
panel.Children.Add(new TextBlock { Text = message, Margin = new Thickness(5, 0, 0, 0), TextWrapping = TextWrapping.Wrap });

EnqueueMessage(queue, panel, duration);
}
Expand Down Expand Up @@ -71,4 +71,4 @@ public static void HandlePreviewMouseWheel(object sender, MouseWheelEventArgs e)
}
}
}
}
}
7 changes: 1 addition & 6 deletions WpfApp/UserAppSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,7 @@ public class UserAppSettings : PermanentConfig<UserAppSettings>
private static readonly object _objlock = new();
private static UserAppSettings? _singleton;

public static UserAppSettings GetSingletonInstance()
{
return GetSingletonInstance(false);
}

public static UserAppSettings GetSingletonInstance(bool forceRecreate)
public static UserAppSettings GetSingletonInstance(bool forceRecreate = false)
{
lock (_objlock)
{
Expand Down
Loading
Loading