Skip to content

Commit f692404

Browse files
authored
Merge pull request #967 from Caliburn-Micro/update_features
Update Avalonia UI features
2 parents d644b15 + 4f4e2ee commit f692404

File tree

5 files changed

+110
-22
lines changed

5 files changed

+110
-22
lines changed

samples/features/Features.Avalonia/ViewModels/ShellViewModel.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ public void GoHome()
4242
}
4343
}
4444

45+
public void GoBack()
46+
{
47+
if (_navigationService != null)
48+
{
49+
_navigationService.GoBackAsync();
50+
}
51+
}
52+
4553
public async void NavReady(NavigationFrame frame)
4654
{
4755
_navigationService = frame as INavigationService;

samples/features/Features.Avalonia/Views/NavigationSourceView.axaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,11 @@
44
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
55
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
66
x:Class="Features.CrossPlatform.Views.NavigationSourceView">
7-
Welcome to Avalonia!
7+
<Grid>
8+
<StackPanel Margin="20">
9+
<TextBox x:Name="Text" />
10+
<CheckBox x:Name="IsNavigationEnabled" Content="Is Enabled" Margin="0,10" />
11+
<Button x:Name="Navigate" Content="Navigate" />
12+
</StackPanel>
13+
</Grid>
814
</UserControl>

samples/features/Features.Avalonia/Views/NavigationTargetView.axaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,10 @@
44
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
55
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
66
x:Class="Features.CrossPlatform.Views.NavigationTargetView">
7-
Welcome to Avalonia!
7+
<Grid>
8+
<StackPanel Margin="20">
9+
<TextBlock x:Name="Text" />
10+
<TextBlock x:Name="IsNavigationEnabled" />
11+
</StackPanel>
12+
</Grid>
813
</UserControl>

samples/features/Features.Avalonia/Views/ShellView.axaml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,29 @@
88
Height="450"
99
x:Class="Features.CrossPlatform.Views.ShellView"
1010
Title="ShellView">
11+
<Window.Resources>
12+
<StreamGeometry x:Key="arrow_left_regular">M12.7347,4.20949 C13.0332,3.92233 13.508,3.93153 13.7952,4.23005 C14.0823,4.52857 14.0731,5.00335 13.7746,5.29051 L5.50039,13.25 L24.2532,13.25 C24.6674,13.25 25.0032,13.5858 25.0032,13.9999982 C25.0032,14.4142 24.6674,14.75 24.2532,14.75 L5.50137,14.75 L13.7746,22.7085 C14.0731,22.9957 14.0823,23.4705 13.7952,23.769 C13.508,24.0675 13.0332,24.0767 12.7347,23.7896 L3.30673,14.7202 C2.89776,14.3268 2.89776,13.6723 3.30673,13.2788 L12.7347,4.20949 Z</StreamGeometry>
13+
<StreamGeometry x:Key="home_regular">M21.6062 5.85517C23.0048 4.71494 24.9952 4.71494 26.3938 5.85517L39.5688 16.5966C40.4736 17.3342 41 18.4492 41 19.628V39.1134C41 41.2599 39.2875 43 37.175 43H32.075C29.9625 43 28.25 41.2599 28.25 39.1134V29.7492C28.25 29.0337 27.6792 28.4536 26.975 28.4536H21.025C20.3208 28.4536 19.75 29.0337 19.75 29.7492V39.1134C19.75 41.2599 18.0375 43 15.925 43H10.825C8.71251 43 7 41.2599 7 39.1134V19.628C7 18.4493 7.52645 17.3342 8.43124 16.5966L21.6062 5.85517ZM24.7979 7.87612C24.3317 7.49604 23.6683 7.49604 23.2021 7.87612L10.0271 18.6175C9.72548 18.8634 9.55 19.2351 9.55 19.628V39.1134C9.55 39.8289 10.1208 40.4089 10.825 40.4089H15.925C16.6292 40.4089 17.2 39.8289 17.2 39.1134V29.7492C17.2 27.6027 18.9125 25.8626 21.025 25.8626H26.975C29.0875 25.8626 30.8 27.6027 30.8 29.7492V39.1134C30.8 39.8289 31.3708 40.4089 32.075 40.4089H37.175C37.8792 40.4089 38.45 39.8289 38.45 39.1134V19.628C38.45 19.2351 38.2745 18.8634 37.9729 18.6175L24.7979 7.87612Z</StreamGeometry> </Window.Resources>
1114
<Grid>
1215
<Grid.RowDefinitions>
1316
<RowDefinition Height="50"></RowDefinition>
1417
<RowDefinition Height="*"></RowDefinition>
1518
</Grid.RowDefinitions>
1619
<StackPanel Grid.Row="0" Orientation="Horizontal">
17-
<Button cal:Message.Attach="GoHome">Home</Button>
20+
<StackPanel.Background>
21+
<LinearGradientBrush StartPoint="50%,0%" EndPoint="50%,100%">
22+
<GradientStop Color="#A8E6CF" Offset="0.0"/>
23+
<GradientStop Color="#3D84A8" Offset="1.0"/>
24+
</LinearGradientBrush>
25+
</StackPanel.Background>
26+
<Button cal:Message.Attach="GoBack" >
27+
<PathIcon Height="25" Width="25" Foreground="Blue"
28+
Data="{StaticResource arrow_left_regular}"/>
29+
</Button>
30+
<Button cal:Message.Attach="GoHome" >
31+
<PathIcon Height="25" Width="25" Foreground="Blue"
32+
Data="{StaticResource home_regular}"/>
33+
</Button>
1834
</StackPanel>
1935
<DockPanel Grid.Row="1">
2036
<Border>

src/Caliburn.Micro.Platform/Platforms/netcore-avalonia/NavigationFrame.cs

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using System;
2+
using System.Collections.Generic;
23
using System.Diagnostics;
34
using System.Threading.Tasks;
45
using Avalonia;
56
using Avalonia.Controls;
7+
using Avalonia.Interactivity;
68

79
namespace Caliburn.Micro
810
{
@@ -15,18 +17,24 @@ public class NavigationFrame : ContentControl, INavigationService
1517
private static readonly ILog Log = LogManager.GetLog(typeof(NavigationFrame));
1618

1719
private string defaultContent { get; } = "Default Content";
18-
20+
private readonly List<object> navigationStack = new List<object>();
21+
private int navigationStackIndex = 0;
1922
/// <summary>
2023
/// Initializes a new instance of the <see cref="NavigationFrame"/> class.
2124
/// </summary>
2225
public NavigationFrame()
2326
{
2427
Content = defaultContent;
25-
this.AttachedToVisualTree += NavigationFrame_AttachedToVisualTree;
26-
LayoutUpdated += NavigationFrame_LayoutUpdated;
28+
this.Loaded += NavigationFrame_Loaded;
2729
ContentProperty.Changed.AddClassHandler<NavigationFrame>((sender, e) => NavigationFrame_ContentChanged(sender, e));
2830
}
2931

32+
private void NavigationFrame_Loaded(object sender, RoutedEventArgs e)
33+
{
34+
Log.Info("Navigation Frame loaded");
35+
OnNavigationServiceReady(new EventArgs());
36+
}
37+
3038
private void NavigationFrame_ContentChanged(NavigationFrame sender, AvaloniaPropertyChangedEventArgs e)
3139
{
3240
Log.Info("Content changed");
@@ -66,15 +74,6 @@ private async void NavigationFrame_TransitionCompleted(object sender, Transition
6674
}
6775
}
6876

69-
/// <summary>
70-
/// Handles the event when the frame is attached to the visual tree.
71-
/// </summary>
72-
private void NavigationFrame_AttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
73-
{
74-
Log.Info("Attached to visual tree");
75-
OnNavigationServiceReady(new EventArgs());
76-
}
77-
7877
/// <summary>
7978
/// Occurs when the navigation service is ready.
8079
/// </summary>
@@ -98,7 +97,7 @@ protected virtual void OnNavigationServiceReady(EventArgs e)
9897
/// Navigates to the specified view model.
9998
/// </summary>
10099
/// <param name="viewModel">The view model to navigate to.</param>
101-
private void NavigateToViewModel(object viewModel)
100+
private void NavigateToViewModel(object viewModel, bool addToStack = true)
102101
{
103102
if (viewModel == null)
104103
{
@@ -117,17 +116,25 @@ private void NavigateToViewModel(object viewModel)
117116

118117
ViewModelBinder.Bind(viewModel, viewInstance, null);
119118
Log.Info($"View Model {viewModel}");
120-
Log.Info($"View {viewInstance}");
121119
Tag = "Navigating";
122120
viewInstance.DataContext = viewModel;
123121
Content = viewInstance;
124-
122+
if (addToStack)
123+
{
124+
navigationStack.Add(viewModel);
125+
navigationStackIndex = navigationStack.Count - 1;
126+
}
125127
}
126128

127129
/// <inheritdoc/>
128130
public Task GoBackAsync(bool animated = true)
129131
{
130-
throw new NotImplementedException();
132+
Log.Info("Going back");
133+
if (navigationStackIndex > 0)
134+
navigationStackIndex--;
135+
136+
NavigateToViewModel(navigationStack[navigationStackIndex], false);
137+
return Task.CompletedTask;
131138
}
132139

133140
/// <inheritdoc/>
@@ -145,18 +152,27 @@ public Task NavigateToViewAsync<T>(object parameter = null, bool animated = true
145152
/// <inheritdoc/>
146153
public Task NavigateToViewModelAsync(Type viewModelType, object parameter = null, bool animated = true)
147154
{
148-
Log.Info($"View model type {viewModelType}");
149155
var vm = Caliburn.Micro.IoC.GetInstance(viewModelType, null);
150-
Log.Info($"VM is null {vm == null}");
156+
TryInjectParameters(vm, parameter);
151157
NavigateToViewModel(vm);
152158

153159
return Task.CompletedTask;
154160
}
155161

162+
/// <summary>
163+
/// Gets or sets the ViewModel.
164+
/// </summary>
165+
public static string ViewModel
166+
{
167+
get; set;
168+
}
169+
156170
/// <inheritdoc/>
157171
public Task NavigateToViewModelAsync<T>(object parameter = null, bool animated = true)
158172
{
159-
throw new NotImplementedException();
173+
Log.Info($"Navigate to View model type {typeof(T)}");
174+
Log.Info($"Navigate to View model parameter not null {parameter != null}");
175+
return NavigateToViewModelAsync(typeof(T), parameter, animated);
160176
}
161177

162178
/// <inheritdoc/>
@@ -170,6 +186,7 @@ public Task NavigateToViewModelAsync(Screen viewModel, object parameter = null,
170186
/// <inheritdoc/>
171187
public Task GoBackToRootAsync(bool animated = true)
172188
{
189+
Log.Info("Going back to root");
173190
throw new NotImplementedException();
174191
}
175192

@@ -181,5 +198,41 @@ private string GetDebuggerDisplay()
181198
{
182199
return $"{nameof(NavigationFrame)}: Content={Content}, IsNavigationServiceReady={NavigationServiceReady != null}";
183200
}
201+
202+
/// <summary>
203+
/// Attempts to inject query string parameters from the view into the view model.
204+
/// </summary>
205+
/// <param name="viewModel"> The view model.</param>
206+
/// <param name="parameter"> The parameter.</param>
207+
protected virtual void TryInjectParameters(object viewModel, object parameter)
208+
{
209+
var viewModelType = viewModel.GetType();
210+
211+
var dictionaryParameter = parameter as IDictionary<string, object>;
212+
213+
if (dictionaryParameter != null)
214+
{
215+
foreach (var pair in dictionaryParameter)
216+
{
217+
var property = viewModelType.GetPropertyCaseInsensitive(pair.Key);
218+
219+
if (property == null)
220+
{
221+
continue;
222+
}
223+
224+
property.SetValue(viewModel, MessageBinder.CoerceValue(property.PropertyType, pair.Value, null), null);
225+
}
226+
}
227+
else
228+
{
229+
var property = viewModelType.GetPropertyCaseInsensitive("Parameter");
230+
231+
if (property == null)
232+
return;
233+
234+
property.SetValue(viewModel, MessageBinder.CoerceValue(property.PropertyType, parameter, null), null);
235+
}
236+
}
184237
}
185238
}

0 commit comments

Comments
 (0)