NavigationPagePassDataPage.xaml.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. using System.Threading.Tasks;
  2. using Avalonia.Controls;
  3. using Avalonia.Interactivity;
  4. using Avalonia.Layout;
  5. using Avalonia.Media;
  6. namespace ControlCatalog.Pages
  7. {
  8. public partial class NavigationPagePassDataPage : UserControl
  9. {
  10. private record Contact(string Name, string Occupation, string Country, Color Color);
  11. private static readonly Contact[] Contacts =
  12. {
  13. new("Alice Johnson", "Software Engineer", "United States", Color.Parse("#4CAF50")),
  14. new("Bob Smith", "Product Designer", "Canada", Color.Parse("#2196F3")),
  15. new("Carol White", "Data Scientist", "United Kingdom", Color.Parse("#9C27B0")),
  16. new("David Lee", "DevOps Engineer", "Australia", Color.Parse("#FF9800")),
  17. new("Emma Brown", "UX Researcher", "Germany", Color.Parse("#F44336")),
  18. };
  19. private bool _initialized;
  20. private bool _isLoaded;
  21. public NavigationPagePassDataPage()
  22. {
  23. InitializeComponent();
  24. Loaded += OnLoaded;
  25. }
  26. private async void OnLoaded(object? sender, RoutedEventArgs e)
  27. {
  28. _isLoaded = true;
  29. if (_initialized)
  30. return;
  31. _initialized = true;
  32. DemoNav.Pushed += (s, ev) => AppendNavigationLog($"Pushed → {ev.Page?.Header}");
  33. DemoNav.Popped += (s, ev) => AppendNavigationLog($"Popped ← {ev.Page?.Header}");
  34. await DemoNav.PushAsync(CreateContactListPage(), null);
  35. }
  36. private async void OnPop(object? sender, RoutedEventArgs e) => await DemoNav.PopAsync();
  37. private void OnMethodChanged(object? sender, SelectionChangedEventArgs e)
  38. {
  39. if (!_isLoaded) return;
  40. if (MethodCombo.SelectedIndex == 0)
  41. {
  42. MethodDescription.Text = "Data is passed as a constructor argument to the detail page. The page stores the contact and displays its properties directly.";
  43. }
  44. else
  45. {
  46. MethodDescription.Text = "Data is passed by setting the new page's DataContext. This enables data binding in XAML to display the data automatically.";
  47. }
  48. }
  49. private ContentPage CreateContactListPage()
  50. {
  51. var list = new StackPanel { Spacing = 8, Margin = new Avalonia.Thickness(16) };
  52. var header = new TextBlock
  53. {
  54. Text = "Contacts",
  55. FontSize = 20,
  56. FontWeight = FontWeight.Bold,
  57. Margin = new Avalonia.Thickness(0, 0, 0, 4),
  58. };
  59. list.Children.Add(header);
  60. var subtitle = new TextBlock
  61. {
  62. Text = "Tap a contact to navigate and pass its data to the detail page.",
  63. FontSize = 13,
  64. Opacity = 0.6,
  65. TextWrapping = TextWrapping.Wrap,
  66. Margin = new Avalonia.Thickness(0, 0, 0, 8),
  67. };
  68. list.Children.Add(subtitle);
  69. foreach (var contact in Contacts)
  70. {
  71. var card = CreateContactCard(contact);
  72. list.Children.Add(card);
  73. }
  74. return new ContentPage
  75. {
  76. Header = "Contacts",
  77. Content = new ScrollViewer { Content = list },
  78. HorizontalContentAlignment = HorizontalAlignment.Stretch,
  79. VerticalContentAlignment = VerticalAlignment.Stretch
  80. };
  81. }
  82. private Button CreateContactCard(Contact contact)
  83. {
  84. var initials = string.Concat(contact.Name.Split(' ')[0][0], contact.Name.Split(' ')[1][0]).ToString();
  85. var card = new Button
  86. {
  87. HorizontalAlignment = HorizontalAlignment.Stretch,
  88. HorizontalContentAlignment = HorizontalAlignment.Left,
  89. Padding = new Avalonia.Thickness(12, 8),
  90. Content = new StackPanel
  91. {
  92. Orientation = Orientation.Horizontal,
  93. Spacing = 12,
  94. Children =
  95. {
  96. new Border
  97. {
  98. Width = 44, Height = 44,
  99. CornerRadius = new Avalonia.CornerRadius(22),
  100. Background = new SolidColorBrush(contact.Color),
  101. Child = new TextBlock
  102. {
  103. Text = initials,
  104. Foreground = Brushes.White,
  105. FontSize = 16,
  106. FontWeight = FontWeight.Bold,
  107. HorizontalAlignment = HorizontalAlignment.Center,
  108. VerticalAlignment = VerticalAlignment.Center
  109. }
  110. },
  111. new StackPanel
  112. {
  113. VerticalAlignment = VerticalAlignment.Center,
  114. Spacing = 2,
  115. Children =
  116. {
  117. new TextBlock { Text = contact.Name, FontSize = 15, FontWeight = FontWeight.SemiBold },
  118. new TextBlock { Text = $"{contact.Occupation} · {contact.Country}", FontSize = 12, Opacity = 0.6 }
  119. }
  120. }
  121. }
  122. }
  123. };
  124. card.Click += async (s, e) => await NavigateToDetail(contact);
  125. return card;
  126. }
  127. private async Task NavigateToDetail(Contact contact)
  128. {
  129. ContentPage detailPage;
  130. var pageBg = new SolidColorBrush(Color.FromArgb(30, contact.Color.R, contact.Color.G, contact.Color.B));
  131. if (MethodCombo.SelectedIndex == 1)
  132. {
  133. // Via DataContext
  134. detailPage = new ContentPage
  135. {
  136. Header = contact.Name,
  137. Background = pageBg,
  138. DataContext = contact,
  139. Content = CreateDetailContent(contact, "DataContext")
  140. };
  141. }
  142. else
  143. {
  144. // Via Constructor argument
  145. detailPage = new ContentPage
  146. {
  147. Header = contact.Name,
  148. Background = pageBg,
  149. Content = CreateDetailContent(contact, "Constructor")
  150. };
  151. }
  152. detailPage.HorizontalContentAlignment = HorizontalAlignment.Stretch;
  153. detailPage.VerticalContentAlignment = VerticalAlignment.Stretch;
  154. await DemoNav.PushAsync(detailPage);
  155. AppendNavigationLog($"Navigated to {contact.Name} via {(MethodCombo.SelectedIndex == 1 ? "DataContext" : "Constructor")}");
  156. }
  157. private static Panel CreateDetailContent(Contact contact, string method)
  158. {
  159. var initials = string.Concat(contact.Name.Split(' ')[0][0], contact.Name.Split(' ')[1][0]).ToString();
  160. return new StackPanel
  161. {
  162. HorizontalAlignment = HorizontalAlignment.Center,
  163. VerticalAlignment = VerticalAlignment.Center,
  164. Spacing = 12,
  165. Children =
  166. {
  167. new Border
  168. {
  169. Width = 80, Height = 80,
  170. CornerRadius = new Avalonia.CornerRadius(40),
  171. Background = new SolidColorBrush(contact.Color),
  172. HorizontalAlignment = HorizontalAlignment.Center,
  173. Child = new TextBlock
  174. {
  175. Text = initials,
  176. Foreground = Brushes.White,
  177. FontSize = 28,
  178. FontWeight = FontWeight.Bold,
  179. HorizontalAlignment = HorizontalAlignment.Center,
  180. VerticalAlignment = VerticalAlignment.Center
  181. }
  182. },
  183. new TextBlock
  184. {
  185. Text = contact.Name,
  186. FontSize = 24,
  187. FontWeight = FontWeight.Bold,
  188. HorizontalAlignment = HorizontalAlignment.Center
  189. },
  190. new Border
  191. {
  192. Background = new SolidColorBrush(Color.Parse("#2196F3")),
  193. CornerRadius = new Avalonia.CornerRadius(4),
  194. Padding = new Avalonia.Thickness(8, 4),
  195. HorizontalAlignment = HorizontalAlignment.Center,
  196. Child = new TextBlock
  197. {
  198. Text = $"Passed via {method}",
  199. FontSize = 11,
  200. Foreground = Brushes.White,
  201. }
  202. },
  203. new TextBlock
  204. {
  205. Text = contact.Occupation,
  206. FontSize = 14,
  207. Opacity = 0.7,
  208. HorizontalAlignment = HorizontalAlignment.Center
  209. },
  210. new TextBlock
  211. {
  212. Text = contact.Country,
  213. FontSize = 13,
  214. Opacity = 0.5,
  215. HorizontalAlignment = HorizontalAlignment.Center
  216. }
  217. }
  218. };
  219. }
  220. private void AppendNavigationLog(string message)
  221. {
  222. var current = NavigationLog.Text;
  223. NavigationLog.Text = string.IsNullOrEmpty(current)
  224. ? message
  225. : $"{current}\n{message}";
  226. }
  227. }
  228. }