Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prism.Avalonia Library #3127

Open
wants to merge 43 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
015a067
Imported Prism.Avalonia v9.0.401.11000-pre raw files (unconverted)
DamianSuess Apr 28, 2024
bd733fe
Updated references
DamianSuess Apr 28, 2024
c9de64e
Prism.Avalonia to use standard Prism icon
DamianSuess Apr 28, 2024
d911be0
Removed unnecessary reference to DryIoc. It now pulls from, Prism.Con…
DamianSuess Apr 28, 2024
945c75c
Code cleanup; removed `this`
DamianSuess Apr 28, 2024
04570dd
Merge branch 'master' into dev/suess/Prism.Avalonia
DamianSuess May 16, 2024
08af037
Merge branch 'master' into dev/suess/Prism.Avalonia
DamianSuess Jun 7, 2024
079b26f
Merge branch 'dev/suess/Prism.Avalonia' of https://github.com/DamianS…
DamianSuess Jun 7, 2024
faa1058
Added tests for dryioc. Prism.Avalonia no longer requires Avalonia.Re…
DamianSuess Jul 27, 2024
ad1c4a7
Updated ItemsControlRegionAdapter to fix previous-binding and allow i…
DamianSuess Aug 4, 2024
39d99e7
notes
DamianSuess Aug 4, 2024
e3cf4c9
Temp removal of container provider extension
DamianSuess Aug 4, 2024
0d3985e
Added Prism.Avalonia tests to solution with notes
DamianSuess Aug 22, 2024
9baea1a
Merge branch 'master' into dev/suess/Prism.Avalonia
DamianSuess Aug 22, 2024
98eb8a2
Added Avalonia build YML
DamianSuess Aug 22, 2024
46f7cca
Synced NuGets with Prism.Avalonia and added libs to Directory.Build.p…
DamianSuess Aug 22, 2024
06f68ca
chore: begin removing duplicate code
dansiegel Aug 28, 2024
ef3274d
Updated exception messages
DamianSuess Aug 31, 2024
366f3fc
readme link
DamianSuess Aug 31, 2024
d4b2a05
Prism.Avalonia.Tests - Disabled ImplicitUsing for code clarity
DamianSuess Aug 31, 2024
d976f0d
Disabled ImplicitUsing for Avalonia test project clarity, adding `usi…
DamianSuess Aug 31, 2024
64717c4
Base sample Prism.Avalonia app
DamianSuess Sep 1, 2024
1d99cd6
Merge pull request #1 from DamianSuess/dev/suess/Prism.Avalonia-Sample
DamianSuess Sep 1, 2024
6a1a0de
Removed unused reference and cleanup
DamianSuess Oct 13, 2024
4bde483
Sample Prism.Avalonia app with binding, sidebar, journaling, notifica…
DamianSuess Oct 13, 2024
5ae5022
Fixed demo style to use assembly not namespace
DamianSuess Oct 13, 2024
765cf35
Merge branch 'master' into dev/suess/Prism.Avalonia
DamianSuess Oct 23, 2024
7e2ea53
Cleanup
DamianSuess Oct 23, 2024
a8c8338
Avalonia cleanup, reducing warnings and added XML documentation
DamianSuess Oct 23, 2024
33c9a49
Prism.DryIoc.Avalonia.Tests includes package GitHubActionsTestLogger
Nov 3, 2024
a89c6e2
Prism.Avalonia test projects, added GitHubActionsTestLogger
Nov 3, 2024
b342c60
Cleanup - removed unused block
Nov 3, 2024
72a959a
Updated readme to include Prism.Avalonia. Removed Prism.Forms build b…
DamianSuess Dec 14, 2024
b083a4e
GitHub build workflow CI and releases for Prism.Avalonia. Readme incl…
DamianSuess Dec 14, 2024
6452d99
Reduced duplicated code in Prism.DryIoc.Avalonia via compile link wit…
DamianSuess Dec 14, 2024
3e214f3
Reduced duplicated code between Prism.Avalonia and Prism.Wpf `Navigat…
DamianSuess Dec 14, 2024
0e64438
Fixed typo in build_avalonia.yml
DamianSuess Dec 14, 2024
58b02da
Reduced code duplication in Prism.Avalonia's Prism.Navigation.Regions…
DamianSuess Dec 15, 2024
424a303
Reduced code duplication between WPF and Avalonia namespace, Prism.Na…
DamianSuess Dec 15, 2024
f10d13c
Reduced code duplication in Prism.Avalonia's Extensions, Interactivit…
DamianSuess Dec 16, 2024
402993e
Prism.Avalonia UTF8-BOM to UTF-8
DamianSuess Dec 16, 2024
a1e9d71
Prism.Avalonia E2E sample - Enhanced NavigationService sample
DamianSuess Dec 16, 2024
f098383
Disabled ImplicitUsing in e2e sample so users know what to include
DamianSuess Dec 16, 2024
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
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<IsUnoProject>$(MSBuildProjectName.Contains('Uno'))</IsUnoProject>
<IsFormsProject>$(MSBuildProjectName.Contains('Forms'))</IsFormsProject>
<IsMauiProject>$(MSBuildProjectName.Contains('Maui'))</IsMauiProject>
<IsAvaloniaProject>$(MSBuildProjectName.Contains('Avalonia'))</IsAvaloniaProject>
<SignAssembly Condition=" ('$(IsCoreProject)' Or '$(IsWpfProject)') ">True</SignAssembly>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)prism.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
Expand All @@ -49,6 +50,7 @@
<PackageTags Condition=" '$(IsWpfProject)' == 'True' ">prism;mvvm;wpf;dependency injection;di</PackageTags>
<PackageTags Condition=" '$(IsUnoProject)' == 'True' ">prism;mvvm;winui;uno-platform;xamarin;webassembly;android;ios;macos;dependency injection;di</PackageTags>
<PackageTags Condition=" '$(IsFormsProject)' == 'True' ">prism;mvvm;uwp;android;ios;xamarin;xamarin.forms;dependency injection;di</PackageTags>
<PackageTags Condition=" '$(IsAvaloniaProject)' == 'True' ">prism;mvvm;axaml;xaml;desktop;navigation;prismavalonia;dialog;linux;macos;avalonia;dependency injection;di</PackageTags>
<IS_PREVIEW Condition=" '$(IS_PREVIEW)' == '' ">false</IS_PREVIEW>
<IS_RELEASE Condition=" '$(IS_RELEASE)' == '' ">false</IS_RELEASE>
<UseWpf>$(IsWpfProject)</UseWpf>
Expand Down
14 changes: 13 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,19 @@
<PackageVersion Include="Uno.UniversalImageLoader" Version="1.9.36" />
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="8.0.0" />
</ItemGroup>
<!-- Tests -->
<!-- Avalonia -->
<ItemGroup Condition=" $(IsAvaloniaProject) == 'true' ">
<PackageVersion Include="Avalonia" Version="11.0.7" />
<PackageVersion Include="Avalonia.Desktop" Version="11.0.7" />
<PackageVersion Include="Avalonia.Diagnostics" Version="11.0.7" />
<PackageVersion Include="Avalonia.LinuxFramebuffer" Version="11.0.7" />
<PackageVersion Include="Avalonia.Markup.Xaml.Loader" Version="11.0.7" />
<PackageVersion Include="Avalonia.ReactiveUI" Version="11.0.7" />
<PackageVersion Include="Avalonia.Themes.Simple" Version="11.0.7" />
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.0.7" />
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="4.7.0" />
</ItemGroup>
<!-- Tests -->
<ItemGroup>
<PackageVersion Include="coverlet.collector" Version="6.0.0" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.3.3" />
Expand Down
34 changes: 33 additions & 1 deletion PrismLibrary.sln
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.4.33213.308
Expand Down Expand Up @@ -93,6 +92,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prism.Events", "src\Prism.E
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prism.Uno.WinUI.Markup", "src\Uno\Prism.Uno.Markup\Prism.Uno.WinUI.Markup.csproj", "{0EA416B6-0AB6-464B-9F4D-206FFCFB262D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Avalonia", "Avalonia", "{8AE1015F-4D62-47EF-A576-2F7411EC20D5}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prism.Avalonia", "src\Avalonia\Prism.Avalonia\Prism.Avalonia.csproj", "{C505C63F-99E6-464F-8C83-1AE4239C19B1}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Prism.DryIoc.Avalonia", "src\Avalonia\Prism.DryIoc.Avalonia\Prism.DryIoc.Avalonia.csproj", "{A6B7B19C-3288-4CD2-A737-527BEB1ED807}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -415,6 +420,30 @@ Global
{0EA416B6-0AB6-464B-9F4D-206FFCFB262D}.Release|x64.Build.0 = Release|Any CPU
{0EA416B6-0AB6-464B-9F4D-206FFCFB262D}.Release|x86.ActiveCfg = Release|Any CPU
{0EA416B6-0AB6-464B-9F4D-206FFCFB262D}.Release|x86.Build.0 = Release|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Debug|x64.ActiveCfg = Debug|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Debug|x64.Build.0 = Debug|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Debug|x86.ActiveCfg = Debug|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Debug|x86.Build.0 = Debug|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Release|Any CPU.Build.0 = Release|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Release|x64.ActiveCfg = Release|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Release|x64.Build.0 = Release|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Release|x86.ActiveCfg = Release|Any CPU
{C505C63F-99E6-464F-8C83-1AE4239C19B1}.Release|x86.Build.0 = Release|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Debug|x64.ActiveCfg = Debug|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Debug|x64.Build.0 = Debug|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Debug|x86.ActiveCfg = Debug|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Debug|x86.Build.0 = Debug|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Release|Any CPU.Build.0 = Release|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Release|x64.ActiveCfg = Release|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Release|x64.Build.0 = Release|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Release|x86.ActiveCfg = Release|Any CPU
{A6B7B19C-3288-4CD2-A737-527BEB1ED807}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -455,6 +484,9 @@ Global
{8711D306-1118-4A11-9399-EF14AA13015E} = {540CEEC1-D541-4614-BF0B-18056A83E434}
{8610485A-BE9F-4938-86D4-E9F1FA1739A0} = {F3664D7A-6FF5-4D1F-9F5F-26EE87F032D3}
{0EA416B6-0AB6-464B-9F4D-206FFCFB262D} = {8F959801-D494-4CAF-9437-90F30472E169}
{8AE1015F-4D62-47EF-A576-2F7411EC20D5} = {F3664D7A-6FF5-4D1F-9F5F-26EE87F032D3}
{C505C63F-99E6-464F-8C83-1AE4239C19B1} = {8AE1015F-4D62-47EF-A576-2F7411EC20D5}
{A6B7B19C-3288-4CD2-A737-527BEB1ED807} = {8AE1015F-4D62-47EF-A576-2F7411EC20D5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C7433AE2-B1A0-4C1A-887E-5CAA7AAF67A6}
Expand Down
12 changes: 12 additions & 0 deletions PrismLibrary_Avalonia.slnf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"solution": {
"path": "PrismLibrary.sln",
"projects": [
"src\\Containers\\Prism.DryIoc.Shared\\Prism.DryIoc.Shared.shproj",
"src\\Avalonia\\Prism.Avalonia\\Prism.Avalonia.csproj",
"src\\Avalonia\\Prism.DryIoc.Avalonia\\Prism.DryIoc.Avalonia.csproj",
"tests\\Avalonia\\Prism.Avalonia.Tests\\Prism.Avalonia.Tests.csproj",
"tests\\Avalonia\\Prism.DryIoc.Avalonia.Tests\\Prism.DryIoc.Avalonia.Tests.csproj"
DamianSuess marked this conversation as resolved.
Show resolved Hide resolved
]
}
}
80 changes: 80 additions & 0 deletions src/Avalonia/Prism.Avalonia/Common/MvvmHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
using System;
using System.ComponentModel;
using Avalonia.Controls;
using Prism.Mvvm;

namespace Prism.Common
{
/// <summary>
/// Helper class for MVVM.
/// </summary>
public static class MvvmHelpers
{
/// <summary>
/// Sets the AutoWireViewModel property to true for the <paramref name="viewOrViewModel"/>.
/// </summary>
/// <remarks>
/// The AutoWireViewModel property will only be set to true if the view
/// is a <see cref="FrameworkElement"/>, the DataContext of the view is null, and
/// the AutoWireViewModel property of the view is null.
/// </remarks>
/// <param name="viewOrViewModel">The View or ViewModel.</param>
[EditorBrowsable(EditorBrowsableState.Never)]
internal static void AutowireViewModel(object viewOrViewModel)
{
if (viewOrViewModel is Control view &&
view.DataContext is null &&
ViewModelLocator.GetAutoWireViewModel(view) is null)
{
ViewModelLocator.SetAutoWireViewModel(view, true);
}
}

////#endif

/// <summary>
/// Perform an <see cref="Action{T}"/> on a view and ViewModel.
/// </summary>
/// <remarks>
/// The action will be performed on the view and its ViewModel if they implement <typeparamref name="T"/>.
/// </remarks>
/// <typeparam name="T">The <see cref="Action{T}"/> parameter type.</typeparam>
/// <param name="view">The view to perform the <see cref="Action{T}"/> on.</param>
/// <param name="action">The <see cref="Action{T}"/> to perform.</param>
public static void ViewAndViewModelAction<T>(object view, Action<T> action) where T : class
{
if (view is T viewAsT)
action(viewAsT);

if (view is Control element && element.DataContext is T viewModelAsT)
{
action(viewModelAsT);
}
}

/// <summary>
/// Get an implementer from a view or ViewModel.
/// </summary>
/// <remarks>
/// If the view implements <typeparamref name="T"/> it will be returned.
/// Otherwise if the view's <see cref="FrameworkElement.DataContext"/> implements <typeparamref name="T"/> it will be returned instead.
/// </remarks>
/// <typeparam name="T">The implementer type to get.</typeparam>
/// <param name="view">The view to get <typeparamref name="T"/> from.</param>
/// <returns>view or ViewModel as <typeparamref name="T"/>.</returns>
public static T GetImplementerFromViewOrViewModel<T>(object view) where T : class
{
if (view is T viewAsT)
{
return viewAsT;
}

if (view is Control element && element.DataContext is T vmAsT)
{
return vmAsT;
}

return null;
}
}
}
57 changes: 57 additions & 0 deletions src/Avalonia/Prism.Avalonia/Common/ObservableObject.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System;
using System.ComponentModel;
using Avalonia;
using Avalonia.Controls;

namespace Prism.Common
{
/// <summary>
/// Class that wraps an object, so that other classes can notify for Change events. Typically, this class is set as
/// a Dependency Property on AvaloniaObjects, and allows other classes to observe any changes in the Value.
/// </summary>
/// <remarks>
/// This class is required, because in Silverlight, it's not possible to receive Change notifications for Dependency properties that you do not own.
/// </remarks>
/// <typeparam name="T">The type of the property that's wrapped in the Observable object</typeparam>
public class ObservableObject<T> : Control, INotifyPropertyChanged
{
/// <summary>
/// Identifies the Value property of the ObservableObject
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes", Justification = "This is the pattern for WPF dependency properties")]
public static readonly StyledProperty<T> ValueProperty =
AvaloniaProperty.Register<Control, T>(name: nameof(Value));

//StyledProperty.Register("Value", typeof(T), typeof(ObservableObject<T>), new PropertyMetadata(ValueChangedCallback));

/// <summary>
/// Event that gets invoked when the Value property changes.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;

/// <summary>
/// The value that's wrapped inside the ObservableObject.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
public T Value
{
get { return (T)this.GetValue(ValueProperty); }
set { this.SetValue(ValueProperty, value); }
}

private static void ValueChangedCallback(AvaloniaObject d, AvaloniaPropertyChangedEventArgs e)
{
ObservableObject<T> thisInstance = ((ObservableObject<T>)d);
PropertyChangedEventHandler eventHandler = thisInstance.PropertyChanged;
if (eventHandler != null)
{
eventHandler(thisInstance, new PropertyChangedEventArgs(nameof(Value)));
}
}

static ObservableObject()
{
ValueProperty.Changed.Subscribe(args => ValueChangedCallback(args?.Sender, args));
}
}
}
76 changes: 76 additions & 0 deletions src/Avalonia/Prism.Avalonia/Dialogs/Dialog.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Styling;

namespace Prism.Dialogs
{
/// <summary>
/// This class contains <see cref="IDialogWindow"/> attached properties.
/// </summary>
public class Dialog
{
/// <summary>Identifies the WindowStyle attached property.</summary>
/// <remarks>This attached property is used to specify the style of a <see cref="IDialogWindow"/>.</remarks>
public static readonly AvaloniaProperty WindowStyleProperty =
AvaloniaProperty.RegisterAttached<AvaloniaObject, Style>("WindowStyle", typeof(Dialog));

/// <summary>Identifies the WindowStartupLocation attached property.</summary>
/// <remarks>This attached property is used to specify the startup location of a <see cref="IDialogWindow"/>.</remarks>
public static readonly AvaloniaProperty WindowStartupLocationProperty =
AvaloniaProperty.RegisterAttached<AvaloniaObject, WindowStartupLocation>(
name: "WindowStartupLocation",
ownerType: typeof(Dialog));

public Dialog()
{
WindowStartupLocationProperty.Changed.Subscribe(args => OnWindowStartupLocationChanged(args?.Sender, args));
}

/// <summary>
/// Gets the value for the <see cref="WindowStyleProperty"/> attached property.
/// </summary>
/// <param name="obj">The target element.</param>
/// <returns>The <see cref="WindowStyleProperty"/> attached to the <paramref name="obj"/> element.</returns>
public static Style GetWindowStyle(AvaloniaObject obj)
{
return (Style)obj.GetValue(WindowStyleProperty);
}

/// <summary>
/// Sets the <see cref="WindowStyleProperty"/> attached property.
/// </summary>
/// <param name="obj">The target element.</param>
/// <param name="value">The Style to attach.</param>
public static void SetWindowStyle(AvaloniaObject obj, Style value)
{
obj.SetValue(WindowStyleProperty, value);
}

/// <summary>
/// Gets the value for the <see cref="WindowStartupLocationProperty"/> attached property.
/// </summary>
/// <param name="obj">The target element.</param>
/// <returns>The <see cref="WindowStartupLocationProperty"/> attached to the <paramref name="obj"/> element.</returns>
public static WindowStartupLocation GetWindowStartupLocation(AvaloniaObject obj)
{
return (WindowStartupLocation)obj.GetValue(WindowStartupLocationProperty);
}

/// <summary>
/// Sets the <see cref="WindowStartupLocationProperty"/> attached property.
/// </summary>
/// <param name="obj">The target element.</param>
/// <param name="value">The WindowStartupLocation to attach.</param>
public static void SetWindowStartupLocation(AvaloniaObject obj, WindowStartupLocation value)
{
obj.SetValue(WindowStartupLocationProperty, value);
}

private static void OnWindowStartupLocationChanged(AvaloniaObject sender, AvaloniaPropertyChangedEventArgs e)
{
if (sender is Window window)
window.WindowStartupLocation = (WindowStartupLocation)e.NewValue;
}
}
}
Loading
Loading