AppTheming and XAML
This commit is contained in:
297
CLAUDE.md
Normal file
297
CLAUDE.md
Normal file
@@ -0,0 +1,297 @@
|
||||
# CLAUDE.md - OpenMaui XAML Reconstruction
|
||||
|
||||
## CURRENT TASK: Reconstruct XAML from Decompiled Code
|
||||
|
||||
The sample applications (ShellDemo, TodoApp, XamlBrowser) were recovered from decompiled DLLs. The XAML files were compiled away - we have only the generated `InitializeComponent()` code. **Screenshots will be provided** to help verify visual accuracy.
|
||||
|
||||
---
|
||||
|
||||
## Project Locations
|
||||
|
||||
| What | Path |
|
||||
|------|------|
|
||||
| **Main codebase** | `/Users/nible/Documents/Gitea/maui-linux/` |
|
||||
| **Samples (target)** | `/Users/nible/Documents/Gitea/maui-linux-samples` |
|
||||
| **Decompiled samples** | `/Users/nible/Documents/GitHub/recovered/source/` |
|
||||
|
||||
---
|
||||
|
||||
## Git Branch
|
||||
|
||||
**Work on `final` branch.** Commit frequently.
|
||||
|
||||
```bash
|
||||
git branch # Should show: * final
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## XAML Reconstruction Overview
|
||||
|
||||
### ShellDemo (10 pages + shell + app)
|
||||
|
||||
| File | Status | Notes |
|
||||
|------|--------|-------|
|
||||
| App.xaml | [ ] | Colors, Styles (ThemedEntry, TitleLabel, etc.) |
|
||||
| AppShell.xaml | [ ] | Shell with FlyoutHeader, 9 FlyoutItems |
|
||||
| HomePage.xaml | [ ] | Welcome screen with logo |
|
||||
| ButtonsPage.xaml | [ ] | Button demos |
|
||||
| TextInputPage.xaml | [ ] | Entry/Editor demos |
|
||||
| SelectionPage.xaml | [ ] | CheckBox, Switch, RadioButton demos |
|
||||
| PickersPage.xaml | [ ] | DatePicker, TimePicker, Picker demos |
|
||||
| ListsPage.xaml | [ ] | CollectionView demos |
|
||||
| ProgressPage.xaml | [ ] | ProgressBar, ActivityIndicator demos |
|
||||
| GridsPage.xaml | [ ] | Grid layout demos |
|
||||
| AboutPage.xaml | [ ] | About information |
|
||||
| DetailPage.xaml | [ ] | Navigation detail page |
|
||||
|
||||
### TodoApp (app + 3 pages)
|
||||
|
||||
| File | Status | Notes |
|
||||
|------|--------|-------|
|
||||
| App.xaml | [ x] | Colors, Icon strings |
|
||||
| TodoListPage.xaml | [x ] | Main list with swipe actions |
|
||||
| NewTodoPage.xaml | [x ] | Add new todo form |
|
||||
| TodoDetailPage.xaml | [ x] | Edit todo details |
|
||||
|
||||
### XamlBrowser (app + 1 page) - Needs Review
|
||||
|
||||
| File | Status | Notes |
|
||||
|------|--------|-------|
|
||||
| App.xaml | [x] | Colors, styles (NavButtonStyle, GoButtonStyle, AddressBarStyle, StatusLabelStyle) |
|
||||
| App.xaml.cs | [x] | BrowserApp with ToggleTheme() |
|
||||
| MainPage.xaml | [x] | Toolbar with nav buttons, address bar, WebView, status bar |
|
||||
| MainPage.xaml.cs | [x] | Navigation logic, progress animation, theme toggle |
|
||||
| MauiProgram.cs | [x] | UseLinuxPlatform() setup |
|
||||
| Program.cs | [x] | LinuxProgramHost entry point |
|
||||
| Resources/Images/*.svg | [x] | 10 toolbar icons (dark/light variants) - retrieved from Google Icons |
|
||||
|
||||
---
|
||||
|
||||
## How to Reconstruct XAML
|
||||
|
||||
### Step 1: Read the decompiled InitializeComponent()
|
||||
|
||||
Look for patterns like:
|
||||
```csharp
|
||||
// Setting a property
|
||||
((BindableObject)val8).SetValue(Label.TextProperty, (object)"OpenMaui");
|
||||
|
||||
// AppThemeBinding (light/dark mode)
|
||||
val7.Light = "White";
|
||||
val7.Dark = "#E0E0E0";
|
||||
|
||||
// StaticResource
|
||||
val.Key = "PrimaryColor";
|
||||
|
||||
// Layout hierarchy
|
||||
((Layout)val12).Children.Add((IView)(object)val6);
|
||||
```
|
||||
|
||||
### Step 2: Convert to XAML
|
||||
|
||||
```csharp
|
||||
// This C#:
|
||||
((BindableObject)val8).SetValue(Label.TextProperty, (object)"OpenMaui");
|
||||
((BindableObject)val8).SetValue(Label.FontSizeProperty, (object)22.0);
|
||||
((BindableObject)val8).SetValue(Label.FontAttributesProperty, (object)(FontAttributes)1);
|
||||
val7.Light = "White";
|
||||
val7.Dark = "#E0E0E0";
|
||||
((BindableObject)val8).SetBinding(Label.TextColorProperty, val74);
|
||||
```
|
||||
|
||||
```xml
|
||||
<!-- Becomes this XAML: -->
|
||||
<Label Text="OpenMaui"
|
||||
FontSize="22"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light=White, Dark=#E0E0E0}" />
|
||||
```
|
||||
|
||||
### Step 3: Verify with screenshots (when provided)
|
||||
|
||||
Compare the reconstructed XAML against the actual screenshots to ensure visual fidelity.
|
||||
|
||||
---
|
||||
|
||||
## App.xaml Resources Reference
|
||||
|
||||
### ShellDemo Colors (extracted from decompiled)
|
||||
|
||||
```xml
|
||||
<!-- Light theme -->
|
||||
<Color x:Key="PrimaryColor">#2196F3</Color>
|
||||
<Color x:Key="PrimaryDarkColor">#1976D2</Color>
|
||||
<Color x:Key="AccentColor">#FF4081</Color>
|
||||
<Color x:Key="PageBackgroundLight">#F8F8F8</Color>
|
||||
<Color x:Key="CardBackgroundLight">#FFFFFF</Color>
|
||||
<Color x:Key="TextPrimaryLight">#212121</Color>
|
||||
<Color x:Key="TextSecondaryLight">#757575</Color>
|
||||
<Color x:Key="BorderLight">#E0E0E0</Color>
|
||||
<Color x:Key="EntryBackgroundLight">#F9F9F9</Color>
|
||||
<Color x:Key="ShellBackgroundLight">#FFFFFF</Color>
|
||||
<Color x:Key="FlyoutBackgroundLight">#FFFFFF</Color>
|
||||
<Color x:Key="ProgressTrackLight">#E0E0E0</Color>
|
||||
|
||||
<!-- Dark theme -->
|
||||
<Color x:Key="PageBackgroundDark">#121212</Color>
|
||||
<Color x:Key="CardBackgroundDark">#1E1E1E</Color>
|
||||
<Color x:Key="TextPrimaryDark">#FFFFFF</Color>
|
||||
<Color x:Key="TextSecondaryDark">#B0B0B0</Color>
|
||||
<Color x:Key="BorderDark">#424242</Color>
|
||||
<Color x:Key="EntryBackgroundDark">#2C2C2C</Color>
|
||||
<Color x:Key="ShellBackgroundDark">#1E1E1E</Color>
|
||||
<Color x:Key="FlyoutBackgroundDark">#1E1E1E</Color>
|
||||
<Color x:Key="ProgressTrackDark">#424242</Color>
|
||||
```
|
||||
|
||||
### ShellDemo Styles (extracted from decompiled)
|
||||
|
||||
- **ThemedEntry**: BackgroundColor, TextColor, PlaceholderColor with AppThemeBinding
|
||||
- **ThemedEditor**: BackgroundColor, TextColor, PlaceholderColor with AppThemeBinding
|
||||
- **TitleLabel**: FontSize=24, FontAttributes=Bold, TextColor with AppThemeBinding
|
||||
- **SubtitleLabel**: FontSize=16, TextColor with AppThemeBinding
|
||||
- **ThemedFrame**: BackgroundColor, BorderColor with AppThemeBinding
|
||||
- **ThemedProgressBar**: ProgressColor=PrimaryColor, BackgroundColor with AppThemeBinding
|
||||
- **PrimaryButton**: BackgroundColor=PrimaryColor, TextColor=White
|
||||
- **SecondaryButton**: Light/dark themed background and text
|
||||
|
||||
### TodoApp Colors
|
||||
|
||||
```xml
|
||||
<Color x:Key="PrimaryColor">#5C6BC0</Color>
|
||||
<Color x:Key="PrimaryDarkColor">#3949AB</Color>
|
||||
<Color x:Key="AccentColor">#26A69A</Color>
|
||||
<Color x:Key="DangerColor">#EF5350</Color>
|
||||
<!-- ... plus light/dark theme colors -->
|
||||
```
|
||||
|
||||
### TodoApp Icons (Material Design)
|
||||
|
||||
```xml
|
||||
<x:String x:Key="IconAdd"></x:String>
|
||||
<x:String x:Key="IconDelete"></x:String>
|
||||
<x:String x:Key="IconSave"></x:String>
|
||||
<x:String x:Key="IconCheck"></x:String>
|
||||
<x:String x:Key="IconEdit"></x:String>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## AppShell.xaml Structure (ShellDemo)
|
||||
|
||||
From decompiled code, the shell has:
|
||||
|
||||
```xml
|
||||
<Shell Title="OpenMaui Controls Demo"
|
||||
FlyoutBehavior="Flyout"
|
||||
FlyoutBackgroundColor="{AppThemeBinding Light={StaticResource FlyoutBackgroundLight}, Dark={StaticResource FlyoutBackgroundDark}}">
|
||||
|
||||
<!-- FlyoutHeader: Grid with logo and title -->
|
||||
<Shell.FlyoutHeader>
|
||||
<Grid BackgroundColor="{AppThemeBinding ...}" HeightRequest="140" Padding="15">
|
||||
<HorizontalStackLayout VerticalOptions="Center" Spacing="12">
|
||||
<Image Source="openmaui_logo.svg" WidthRequest="60" HeightRequest="60" />
|
||||
<VerticalStackLayout VerticalOptions="Center">
|
||||
<Label Text="OpenMaui" FontSize="22" FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light=White, Dark=#E0E0E0}" />
|
||||
<Label Text="Controls Demo" FontSize="13" Opacity="0.9"
|
||||
TextColor="{AppThemeBinding Light=White, Dark=#B0B0B0}" />
|
||||
</VerticalStackLayout>
|
||||
</HorizontalStackLayout>
|
||||
</Grid>
|
||||
</Shell.FlyoutHeader>
|
||||
|
||||
<!-- FlyoutItems with emoji icons -->
|
||||
<FlyoutItem Title="Home" Route="Home">
|
||||
<FlyoutItem.Icon><FontImageSource Glyph="🏠" FontFamily="Default" Color="{AppThemeBinding ...}" /></FlyoutItem.Icon>
|
||||
<ShellContent ContentTemplate="{DataTemplate local:HomePage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
<FlyoutItem Title="Buttons" Route="Buttons">...</FlyoutItem>
|
||||
<FlyoutItem Title="Text Input" Route="TextInput">...</FlyoutItem>
|
||||
<FlyoutItem Title="Selection" Route="Selection">...</FlyoutItem>
|
||||
<FlyoutItem Title="Pickers" Route="Pickers">...</FlyoutItem>
|
||||
<FlyoutItem Title="Lists" Route="Lists">...</FlyoutItem>
|
||||
<FlyoutItem Title="Progress" Route="Progress">...</FlyoutItem>
|
||||
<FlyoutItem Title="Grids" Route="Grids">...</FlyoutItem>
|
||||
<FlyoutItem Title="About" Route="About">...</FlyoutItem>
|
||||
</Shell>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Decompiled File Locations
|
||||
|
||||
| Sample | Decompiled Path |
|
||||
|--------|-----------------|
|
||||
| ShellDemo | `/Users/nible/Documents/GitHub/recovered/source/ShellDemo/ShellDemo/` |
|
||||
| TodoApp | `/Users/nible/Documents/GitHub/recovered/source/TodoApp/TodoApp/` |
|
||||
| XamlBrowser | `/Users/nible/Documents/GitHub/recovered/source/XamlBrowser/XamlBrowser/` |
|
||||
|
||||
---
|
||||
|
||||
## Build Command
|
||||
|
||||
```bash
|
||||
cd /Users/nible/Documents/GitHub/maui-linux-main
|
||||
dotnet build OpenMaui.Controls.Linux.csproj
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Key Patterns in Decompiled Code
|
||||
|
||||
### 1. Color Values
|
||||
```csharp
|
||||
Color val = new Color(11f / 85f, 0.5882353f, 81f / 85f, 1f);
|
||||
// = Color.FromRgba(0.129, 0.588, 0.953, 1.0) = #2196F3
|
||||
```
|
||||
|
||||
### 2. AppThemeBinding
|
||||
```csharp
|
||||
AppThemeBindingExtension val7 = new AppThemeBindingExtension();
|
||||
val7.Light = "White";
|
||||
val7.Dark = "#E0E0E0";
|
||||
```
|
||||
Becomes: `{AppThemeBinding Light=White, Dark=#E0E0E0}`
|
||||
|
||||
### 3. StaticResource
|
||||
```csharp
|
||||
val.Key = "PrimaryColor";
|
||||
```
|
||||
Becomes: `{StaticResource PrimaryColor}`
|
||||
|
||||
### 4. Layout Hierarchy
|
||||
```csharp
|
||||
((Layout)val12).Children.Add((IView)(object)val6);
|
||||
((Layout)val12).Children.Add((IView)(object)val11);
|
||||
```
|
||||
The children are added in order - first child is val6, second is val11.
|
||||
|
||||
### 5. FontAttributes Enum
|
||||
```csharp
|
||||
(FontAttributes)1 // Bold
|
||||
(FontAttributes)2 // Italic
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Workflow for Each File
|
||||
|
||||
1. **Read decompiled** `InitializeComponent()` method
|
||||
2. **Extract** all UI elements and their properties
|
||||
3. **Write XAML** with proper structure
|
||||
4. **Create code-behind** (usually just constructor calling InitializeComponent)
|
||||
5. **Verify** against screenshot if available
|
||||
6. **Update tracking** in this file
|
||||
7. **Commit** with descriptive message
|
||||
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
- The decompiled code has ALL the information needed - it's just in C# form instead of XAML
|
||||
- Screenshots will help verify visual accuracy
|
||||
- Focus on one file at a time
|
||||
- Commit after each completed file
|
||||
@@ -1,78 +0,0 @@
|
||||
// ShellDemo App - Comprehensive Control Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
/// <summary>
|
||||
/// Main application class with Shell navigation.
|
||||
/// </summary>
|
||||
public class App : Application
|
||||
{
|
||||
public App()
|
||||
{
|
||||
MainPage = new AppShell();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shell definition with flyout menu - comprehensive control demo.
|
||||
/// </summary>
|
||||
public class AppShell : Shell
|
||||
{
|
||||
public AppShell()
|
||||
{
|
||||
FlyoutBehavior = FlyoutBehavior.Flyout;
|
||||
Title = "OpenMaui Controls Demo";
|
||||
|
||||
// Register routes for push navigation (pages not in flyout)
|
||||
Routing.RegisterRoute("detail", typeof(DetailPage));
|
||||
|
||||
// Home
|
||||
Items.Add(CreateFlyoutItem("Home", typeof(HomePage)));
|
||||
|
||||
// Buttons Demo
|
||||
Items.Add(CreateFlyoutItem("Buttons", typeof(ButtonsPage)));
|
||||
|
||||
// Text Input Demo
|
||||
Items.Add(CreateFlyoutItem("Text Input", typeof(TextInputPage)));
|
||||
|
||||
// Selection Controls Demo
|
||||
Items.Add(CreateFlyoutItem("Selection", typeof(SelectionPage)));
|
||||
|
||||
// Pickers Demo
|
||||
Items.Add(CreateFlyoutItem("Pickers", typeof(PickersPage)));
|
||||
|
||||
// Lists Demo
|
||||
Items.Add(CreateFlyoutItem("Lists", typeof(ListsPage)));
|
||||
|
||||
// Progress Demo
|
||||
Items.Add(CreateFlyoutItem("Progress", typeof(ProgressPage)));
|
||||
|
||||
// Grids Demo
|
||||
Items.Add(CreateFlyoutItem("Grids", typeof(GridsPage)));
|
||||
|
||||
// About
|
||||
Items.Add(CreateFlyoutItem("About", typeof(AboutPage)));
|
||||
}
|
||||
|
||||
private FlyoutItem CreateFlyoutItem(string title, Type pageType)
|
||||
{
|
||||
// Route is required for Shell.GoToAsync navigation to work
|
||||
var route = title.Replace(" ", "");
|
||||
return new FlyoutItem
|
||||
{
|
||||
Title = title,
|
||||
Route = route,
|
||||
Items =
|
||||
{
|
||||
new ShellContent
|
||||
{
|
||||
Title = title,
|
||||
Route = route,
|
||||
ContentTemplate = new DataTemplate(pageType)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
150
ShellDemo/App.xaml
Normal file
150
ShellDemo/App.xaml
Normal file
@@ -0,0 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.App">
|
||||
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
|
||||
<!-- Primary Colors -->
|
||||
<Color x:Key="PrimaryColor">#2196F3</Color>
|
||||
<Color x:Key="PrimaryDarkColor">#1976D2</Color>
|
||||
<Color x:Key="AccentColor">#FF4081</Color>
|
||||
<Color x:Key="SuccessColor">#4CAF50</Color>
|
||||
<Color x:Key="WarningColor">#FF9800</Color>
|
||||
<Color x:Key="DangerColor">#F44336</Color>
|
||||
<Color x:Key="PurpleColor">#9C27B0</Color>
|
||||
|
||||
<!-- Light Theme Colors -->
|
||||
<Color x:Key="PageBackgroundLight">#F8F8F8</Color>
|
||||
<Color x:Key="CardBackgroundLight">#FFFFFF</Color>
|
||||
<Color x:Key="TextPrimaryLight">#212121</Color>
|
||||
<Color x:Key="TextSecondaryLight">#757575</Color>
|
||||
<Color x:Key="BorderLight">#E0E0E0</Color>
|
||||
<Color x:Key="EntryBackgroundLight">#F9F9F9</Color>
|
||||
<Color x:Key="ShellBackgroundLight">#FFFFFF</Color>
|
||||
<Color x:Key="FlyoutBackgroundLight">#FFFFFF</Color>
|
||||
<Color x:Key="FlyoutHeaderBackgroundLight">#1976D2</Color>
|
||||
<Color x:Key="ProgressTrackLight">#E0E0E0</Color>
|
||||
|
||||
<!-- Dark Theme Colors -->
|
||||
<Color x:Key="PageBackgroundDark">#121212</Color>
|
||||
<Color x:Key="CardBackgroundDark">#1E1E1E</Color>
|
||||
<Color x:Key="TextPrimaryDark">#FFFFFF</Color>
|
||||
<Color x:Key="TextSecondaryDark">#B0B0B0</Color>
|
||||
<Color x:Key="BorderDark">#424242</Color>
|
||||
<Color x:Key="EntryBackgroundDark">#2C2C2C</Color>
|
||||
<Color x:Key="ShellBackgroundDark">#1E1E1E</Color>
|
||||
<Color x:Key="FlyoutBackgroundDark">#1E1E1E</Color>
|
||||
<Color x:Key="FlyoutHeaderBackgroundDark">#0D47A1</Color>
|
||||
<Color x:Key="ProgressTrackDark">#424242</Color>
|
||||
|
||||
<!-- Themed Entry Style -->
|
||||
<Style x:Key="ThemedEntry" TargetType="Entry">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource EntryBackgroundLight}, Dark={StaticResource EntryBackgroundDark}}" />
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</Style>
|
||||
|
||||
<!-- Themed Editor Style -->
|
||||
<Style x:Key="ThemedEditor" TargetType="Editor">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource EntryBackgroundLight}, Dark={StaticResource EntryBackgroundDark}}" />
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Setter Property="PlaceholderColor" Value="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</Style>
|
||||
|
||||
<!-- Title Label Style -->
|
||||
<Style x:Key="TitleLabel" TargetType="Label">
|
||||
<Setter Property="FontSize" Value="24" />
|
||||
<Setter Property="FontAttributes" Value="Bold" />
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</Style>
|
||||
|
||||
<!-- Subtitle Label Style -->
|
||||
<Style x:Key="SubtitleLabel" TargetType="Label">
|
||||
<Setter Property="FontSize" Value="16" />
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</Style>
|
||||
|
||||
<!-- Body Label Style -->
|
||||
<Style x:Key="BodyLabel" TargetType="Label">
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</Style>
|
||||
|
||||
<!-- Caption Label Style -->
|
||||
<Style x:Key="CaptionLabel" TargetType="Label">
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</Style>
|
||||
|
||||
<!-- Themed Frame Style -->
|
||||
<Style x:Key="ThemedFrame" TargetType="Frame">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource CardBackgroundLight}, Dark={StaticResource CardBackgroundDark}}" />
|
||||
<Setter Property="BorderColor" Value="{AppThemeBinding Light={StaticResource BorderLight}, Dark={StaticResource BorderDark}}" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
<Setter Property="Padding" Value="15" />
|
||||
</Style>
|
||||
|
||||
<!-- Themed Border Style -->
|
||||
<Style x:Key="ThemedBorder" TargetType="Border">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource CardBackgroundLight}, Dark={StaticResource CardBackgroundDark}}" />
|
||||
<Setter Property="Stroke" Value="{AppThemeBinding Light={StaticResource BorderLight}, Dark={StaticResource BorderDark}}" />
|
||||
<Setter Property="StrokeThickness" Value="1" />
|
||||
</Style>
|
||||
|
||||
<!-- Themed Card Border Style -->
|
||||
<Style x:Key="ThemedCard" TargetType="Border">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light={StaticResource CardBackgroundLight}, Dark={StaticResource CardBackgroundDark}}" />
|
||||
<Setter Property="StrokeThickness" Value="0" />
|
||||
<Setter Property="Padding" Value="15" />
|
||||
<Setter Property="StrokeShape">
|
||||
<Setter.Value>
|
||||
<RoundRectangle CornerRadius="8" />
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
<!-- Themed ProgressBar Style -->
|
||||
<Style x:Key="ThemedProgressBar" TargetType="ProgressBar">
|
||||
<Setter Property="ProgressColor" Value="{StaticResource PrimaryColor}" />
|
||||
</Style>
|
||||
|
||||
<!-- Primary Button Style -->
|
||||
<Style x:Key="PrimaryButton" TargetType="Button">
|
||||
<Setter Property="BackgroundColor" Value="{StaticResource PrimaryColor}" />
|
||||
<Setter Property="TextColor" Value="White" />
|
||||
<Setter Property="CornerRadius" Value="5" />
|
||||
</Style>
|
||||
|
||||
<!-- Secondary Button Style -->
|
||||
<Style x:Key="SecondaryButton" TargetType="Button">
|
||||
<Setter Property="BackgroundColor" Value="{AppThemeBinding Light=#E0E0E0, Dark=#424242}" />
|
||||
<Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Setter Property="CornerRadius" Value="5" />
|
||||
</Style>
|
||||
|
||||
<!-- Success Button Style -->
|
||||
<Style x:Key="SuccessButton" TargetType="Button">
|
||||
<Setter Property="BackgroundColor" Value="{StaticResource SuccessColor}" />
|
||||
<Setter Property="TextColor" Value="White" />
|
||||
<Setter Property="CornerRadius" Value="5" />
|
||||
</Style>
|
||||
|
||||
<!-- Danger Button Style -->
|
||||
<Style x:Key="DangerButton" TargetType="Button">
|
||||
<Setter Property="BackgroundColor" Value="{StaticResource DangerColor}" />
|
||||
<Setter Property="TextColor" Value="White" />
|
||||
<Setter Property="CornerRadius" Value="5" />
|
||||
</Style>
|
||||
|
||||
<!-- Themed BoxView Divider -->
|
||||
<Style x:Key="ThemedDivider" TargetType="BoxView">
|
||||
<Setter Property="HeightRequest" Value="1" />
|
||||
<Setter Property="Color" Value="{AppThemeBinding Light={StaticResource BorderLight}, Dark={StaticResource BorderDark}}" />
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
|
||||
</Application>
|
||||
14
ShellDemo/App.xaml.cs
Normal file
14
ShellDemo/App.xaml.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
// App.xaml.cs - Main Application code-behind
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class App : Application
|
||||
{
|
||||
public App()
|
||||
{
|
||||
InitializeComponent();
|
||||
MainPage = new AppShell();
|
||||
}
|
||||
}
|
||||
136
ShellDemo/AppShell.xaml
Normal file
136
ShellDemo/AppShell.xaml
Normal file
@@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Shell xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:local="clr-namespace:ShellDemo"
|
||||
x:Class="ShellDemo.AppShell"
|
||||
Title="OpenMaui Controls Demo"
|
||||
FlyoutBehavior="Flyout"
|
||||
FlyoutBackgroundColor="{AppThemeBinding Light={StaticResource FlyoutBackgroundLight}, Dark={StaticResource FlyoutBackgroundDark}}"
|
||||
Shell.BackgroundColor="{AppThemeBinding Light={StaticResource ShellBackgroundLight}, Dark={StaticResource ShellBackgroundDark}}"
|
||||
Shell.ForegroundColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}"
|
||||
Shell.TitleColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}">
|
||||
|
||||
<!-- Flyout Header -->
|
||||
<Shell.FlyoutHeader>
|
||||
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource FlyoutHeaderBackgroundLight}, Dark={StaticResource FlyoutHeaderBackgroundDark}}"
|
||||
HeightRequest="140"
|
||||
Padding="15">
|
||||
<HorizontalStackLayout VerticalOptions="Center" Spacing="12">
|
||||
<Border WidthRequest="60"
|
||||
HeightRequest="60"
|
||||
StrokeThickness="0"
|
||||
BackgroundColor="{AppThemeBinding Light=White, Dark=#2C2C2C}">
|
||||
<Border.StrokeShape>
|
||||
<RoundRectangle CornerRadius="30" />
|
||||
</Border.StrokeShape>
|
||||
<Label Text="OM"
|
||||
FontSize="24"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{StaticResource PrimaryColor}"
|
||||
HorizontalOptions="Center"
|
||||
VerticalOptions="Center" />
|
||||
</Border>
|
||||
<VerticalStackLayout VerticalOptions="Center">
|
||||
<Label Text="OpenMaui"
|
||||
FontSize="22"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light=White, Dark=#E0E0E0}" />
|
||||
<Label Text="Controls Demo"
|
||||
FontSize="13"
|
||||
TextColor="{AppThemeBinding Light=#E0E0E0, Dark=#B0B0B0}" />
|
||||
</VerticalStackLayout>
|
||||
</HorizontalStackLayout>
|
||||
</Grid>
|
||||
</Shell.FlyoutHeader>
|
||||
|
||||
<!-- Home -->
|
||||
<FlyoutItem Title="Home" Route="Home">
|
||||
<FlyoutItem.Icon>
|
||||
<FontImageSource Glyph="🏠"
|
||||
FontFamily="Default"
|
||||
Color="{AppThemeBinding Light={StaticResource PrimaryColor}, Dark={StaticResource PrimaryColor}}" />
|
||||
</FlyoutItem.Icon>
|
||||
<ShellContent ContentTemplate="{DataTemplate local:HomePage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
<!-- Buttons -->
|
||||
<FlyoutItem Title="Buttons" Route="Buttons">
|
||||
<FlyoutItem.Icon>
|
||||
<FontImageSource Glyph="🔘"
|
||||
FontFamily="Default"
|
||||
Color="{AppThemeBinding Light={StaticResource PrimaryColor}, Dark={StaticResource PrimaryColor}}" />
|
||||
</FlyoutItem.Icon>
|
||||
<ShellContent ContentTemplate="{DataTemplate local:ButtonsPage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
<!-- Text Input -->
|
||||
<FlyoutItem Title="Text Input" Route="TextInput">
|
||||
<FlyoutItem.Icon>
|
||||
<FontImageSource Glyph="📝"
|
||||
FontFamily="Default"
|
||||
Color="{AppThemeBinding Light={StaticResource PrimaryColor}, Dark={StaticResource PrimaryColor}}" />
|
||||
</FlyoutItem.Icon>
|
||||
<ShellContent ContentTemplate="{DataTemplate local:TextInputPage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
<!-- Selection -->
|
||||
<FlyoutItem Title="Selection" Route="Selection">
|
||||
<FlyoutItem.Icon>
|
||||
<FontImageSource Glyph="☑"
|
||||
FontFamily="Default"
|
||||
Color="{AppThemeBinding Light={StaticResource PrimaryColor}, Dark={StaticResource PrimaryColor}}" />
|
||||
</FlyoutItem.Icon>
|
||||
<ShellContent ContentTemplate="{DataTemplate local:SelectionPage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
<!-- Pickers -->
|
||||
<FlyoutItem Title="Pickers" Route="Pickers">
|
||||
<FlyoutItem.Icon>
|
||||
<FontImageSource Glyph="📅"
|
||||
FontFamily="Default"
|
||||
Color="{AppThemeBinding Light={StaticResource PrimaryColor}, Dark={StaticResource PrimaryColor}}" />
|
||||
</FlyoutItem.Icon>
|
||||
<ShellContent ContentTemplate="{DataTemplate local:PickersPage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
<!-- Lists -->
|
||||
<FlyoutItem Title="Lists" Route="Lists">
|
||||
<FlyoutItem.Icon>
|
||||
<FontImageSource Glyph="📋"
|
||||
FontFamily="Default"
|
||||
Color="{AppThemeBinding Light={StaticResource PrimaryColor}, Dark={StaticResource PrimaryColor}}" />
|
||||
</FlyoutItem.Icon>
|
||||
<ShellContent ContentTemplate="{DataTemplate local:ListsPage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
<!-- Progress -->
|
||||
<FlyoutItem Title="Progress" Route="Progress">
|
||||
<FlyoutItem.Icon>
|
||||
<FontImageSource Glyph="⏳"
|
||||
FontFamily="Default"
|
||||
Color="{AppThemeBinding Light={StaticResource PrimaryColor}, Dark={StaticResource PrimaryColor}}" />
|
||||
</FlyoutItem.Icon>
|
||||
<ShellContent ContentTemplate="{DataTemplate local:ProgressPage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
<!-- Grids -->
|
||||
<FlyoutItem Title="Grids" Route="Grids">
|
||||
<FlyoutItem.Icon>
|
||||
<FontImageSource Glyph="📊"
|
||||
FontFamily="Default"
|
||||
Color="{AppThemeBinding Light={StaticResource PrimaryColor}, Dark={StaticResource PrimaryColor}}" />
|
||||
</FlyoutItem.Icon>
|
||||
<ShellContent ContentTemplate="{DataTemplate local:GridsPage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
<!-- About -->
|
||||
<FlyoutItem Title="About" Route="About">
|
||||
<FlyoutItem.Icon>
|
||||
<FontImageSource Glyph="ℹ"
|
||||
FontFamily="Default"
|
||||
Color="{AppThemeBinding Light={StaticResource PrimaryColor}, Dark={StaticResource PrimaryColor}}" />
|
||||
</FlyoutItem.Icon>
|
||||
<ShellContent ContentTemplate="{DataTemplate local:AboutPage}" />
|
||||
</FlyoutItem>
|
||||
|
||||
</Shell>
|
||||
16
ShellDemo/AppShell.xaml.cs
Normal file
16
ShellDemo/AppShell.xaml.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
// AppShell - Shell navigation with flyout menu
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class AppShell : Shell
|
||||
{
|
||||
public AppShell()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Register routes for push navigation (pages not in flyout)
|
||||
Routing.RegisterRoute("detail", typeof(DetailPage));
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
// AboutPage - Information about OpenMaui Linux
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public class AboutPage : ContentPage
|
||||
{
|
||||
public AboutPage()
|
||||
{
|
||||
Title = "About";
|
||||
|
||||
Content = new ScrollView
|
||||
{
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = new Thickness(20),
|
||||
Spacing = 20,
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = "OpenMaui Linux",
|
||||
FontSize = 32,
|
||||
FontAttributes = FontAttributes.Bold,
|
||||
TextColor = Color.FromArgb("#1A237E"),
|
||||
HorizontalOptions = LayoutOptions.Center
|
||||
},
|
||||
new Label
|
||||
{
|
||||
Text = "Version 1.0.0",
|
||||
FontSize = 16,
|
||||
TextColor = Colors.Gray,
|
||||
HorizontalOptions = LayoutOptions.Center
|
||||
},
|
||||
new BoxView { HeightRequest = 1, Color = Colors.LightGray },
|
||||
new Label
|
||||
{
|
||||
Text = "OpenMaui Linux brings .NET MAUI to Linux desktops using SkiaSharp for rendering. " +
|
||||
"It provides a native Linux experience while maintaining compatibility with MAUI's cross-platform API.",
|
||||
FontSize = 14,
|
||||
LineBreakMode = LineBreakMode.WordWrap
|
||||
},
|
||||
CreateInfoCard("Platform", "Linux (X11/Wayland)"),
|
||||
CreateInfoCard("Rendering", "SkiaSharp"),
|
||||
CreateInfoCard("Framework", ".NET MAUI"),
|
||||
CreateInfoCard("License", "MIT License"),
|
||||
new BoxView { HeightRequest = 1, Color = Colors.LightGray },
|
||||
new Label
|
||||
{
|
||||
Text = "Features",
|
||||
FontSize = 20,
|
||||
FontAttributes = FontAttributes.Bold
|
||||
},
|
||||
CreateFeatureItem("Full XAML support with styles and resources"),
|
||||
CreateFeatureItem("Shell navigation with flyout menus"),
|
||||
CreateFeatureItem("All standard MAUI controls"),
|
||||
CreateFeatureItem("Data binding and MVVM"),
|
||||
CreateFeatureItem("Keyboard and mouse input"),
|
||||
CreateFeatureItem("High DPI support"),
|
||||
new BoxView { HeightRequest = 1, Color = Colors.LightGray },
|
||||
new Label
|
||||
{
|
||||
Text = "https://github.com/pablotoledo/OpenMaui-Linux",
|
||||
FontSize = 12,
|
||||
TextColor = Colors.Blue,
|
||||
HorizontalOptions = LayoutOptions.Center
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Frame CreateInfoCard(string label, string value)
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
CornerRadius = 8,
|
||||
Padding = new Thickness(15),
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5"),
|
||||
HasShadow = false,
|
||||
Content = new HorizontalStackLayout
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = label + ":",
|
||||
FontAttributes = FontAttributes.Bold,
|
||||
WidthRequest = 100
|
||||
},
|
||||
new Label
|
||||
{
|
||||
Text = value,
|
||||
TextColor = Colors.Gray
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateFeatureItem(string text)
|
||||
{
|
||||
return new HorizontalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "✓", TextColor = Color.FromArgb("#4CAF50"), FontSize = 16 },
|
||||
new Label { Text = text, FontSize = 14 }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
120
ShellDemo/Pages/AboutPage.xaml
Normal file
120
ShellDemo/Pages/AboutPage.xaml
Normal file
@@ -0,0 +1,120 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.AboutPage"
|
||||
Title="About"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<ScrollView>
|
||||
<VerticalStackLayout Padding="20" Spacing="20">
|
||||
|
||||
<!-- Header -->
|
||||
<Label Text="OpenMaui Linux"
|
||||
FontSize="32"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light=#1A237E, Dark=#7986CB}"
|
||||
HorizontalOptions="Center" />
|
||||
|
||||
<Label Text="Version 1.0.0"
|
||||
FontSize="16"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
HorizontalOptions="Center" />
|
||||
|
||||
<BoxView Style="{StaticResource ThemedDivider}" />
|
||||
|
||||
<Label Text="OpenMaui Linux brings .NET MAUI to Linux desktops using SkiaSharp for rendering. It provides a native Linux experience while maintaining compatibility with MAUI's cross-platform API."
|
||||
FontSize="14"
|
||||
LineBreakMode="WordWrap"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Info Cards -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<HorizontalStackLayout>
|
||||
<Label Text="Platform:" FontAttributes="Bold" WidthRequest="100"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Label Text="Linux (X11/Wayland)"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
</Border>
|
||||
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<HorizontalStackLayout>
|
||||
<Label Text="Rendering:" FontAttributes="Bold" WidthRequest="100"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Label Text="SkiaSharp"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
</Border>
|
||||
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<HorizontalStackLayout>
|
||||
<Label Text="Framework:" FontAttributes="Bold" WidthRequest="100"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Label Text=".NET MAUI"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
</Border>
|
||||
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<HorizontalStackLayout>
|
||||
<Label Text="License:" FontAttributes="Bold" WidthRequest="100"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Label Text="MIT License"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
</Border>
|
||||
|
||||
<BoxView Style="{StaticResource ThemedDivider}" />
|
||||
|
||||
<!-- Features Section -->
|
||||
<Label Text="Features"
|
||||
FontSize="20"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Label Text="✓" TextColor="{StaticResource SuccessColor}" FontSize="16" />
|
||||
<Label Text="Full XAML support with styles and resources" FontSize="14"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Label Text="✓" TextColor="{StaticResource SuccessColor}" FontSize="16" />
|
||||
<Label Text="Shell navigation with flyout menus" FontSize="14"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Label Text="✓" TextColor="{StaticResource SuccessColor}" FontSize="16" />
|
||||
<Label Text="All standard MAUI controls" FontSize="14"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Label Text="✓" TextColor="{StaticResource SuccessColor}" FontSize="16" />
|
||||
<Label Text="Data binding and MVVM" FontSize="14"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Label Text="✓" TextColor="{StaticResource SuccessColor}" FontSize="16" />
|
||||
<Label Text="Keyboard and mouse input" FontSize="14"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Label Text="✓" TextColor="{StaticResource SuccessColor}" FontSize="16" />
|
||||
<Label Text="High DPI support" FontSize="14"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<BoxView Style="{StaticResource ThemedDivider}" />
|
||||
|
||||
<Label Text="https://github.com/pablotoledo/OpenMaui-Linux"
|
||||
FontSize="12"
|
||||
TextColor="{StaticResource PrimaryColor}"
|
||||
HorizontalOptions="Center" />
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
||||
13
ShellDemo/Pages/AboutPage.xaml.cs
Normal file
13
ShellDemo/Pages/AboutPage.xaml.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
// AboutPage - Information about OpenMaui Linux
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class AboutPage : ContentPage
|
||||
{
|
||||
public AboutPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
// ButtonsPage - Comprehensive Button Control Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public class ButtonsPage : ContentPage
|
||||
{
|
||||
private readonly Label _eventLog;
|
||||
private int _eventCount = 0;
|
||||
|
||||
public ButtonsPage()
|
||||
{
|
||||
Title = "Buttons Demo";
|
||||
|
||||
_eventLog = new Label
|
||||
{
|
||||
Text = "Events will appear here...",
|
||||
FontSize = 11,
|
||||
TextColor = Colors.Gray,
|
||||
LineBreakMode = LineBreakMode.WordWrap
|
||||
};
|
||||
|
||||
Content = new Grid
|
||||
{
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
|
||||
new RowDefinition { Height = new GridLength(120) }
|
||||
},
|
||||
Children =
|
||||
{
|
||||
CreateMainContent(),
|
||||
CreateEventLogPanel()
|
||||
}
|
||||
};
|
||||
|
||||
Grid.SetRow((View)((Grid)Content).Children[0], 0);
|
||||
Grid.SetRow((View)((Grid)Content).Children[1], 1);
|
||||
}
|
||||
|
||||
private View CreateMainContent()
|
||||
{
|
||||
return new ScrollView
|
||||
{
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = new Thickness(20),
|
||||
Spacing = 20,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "Button Styles & Events", FontSize = 24, FontAttributes = FontAttributes.Bold },
|
||||
|
||||
// Basic Buttons
|
||||
CreateSection("Basic Buttons", CreateBasicButtons()),
|
||||
|
||||
// Styled Buttons
|
||||
CreateSection("Styled Buttons", CreateStyledButtons()),
|
||||
|
||||
// Button States
|
||||
CreateSection("Button States", CreateButtonStates()),
|
||||
|
||||
// Button with Icons (text simulation)
|
||||
CreateSection("Button Variations", CreateButtonVariations())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateBasicButtons()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 10 };
|
||||
|
||||
var defaultBtn = new Button { Text = "Default Button" };
|
||||
defaultBtn.Clicked += (s, e) => LogEvent("Default Button clicked");
|
||||
defaultBtn.Pressed += (s, e) => LogEvent("Default Button pressed");
|
||||
defaultBtn.Released += (s, e) => LogEvent("Default Button released");
|
||||
|
||||
var textBtn = new Button { Text = "Text Only", BackgroundColor = Colors.Transparent, TextColor = Colors.Blue };
|
||||
textBtn.Clicked += (s, e) => LogEvent("Text Button clicked");
|
||||
|
||||
layout.Children.Add(defaultBtn);
|
||||
layout.Children.Add(textBtn);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateStyledButtons()
|
||||
{
|
||||
var layout = new HorizontalStackLayout { Spacing = 10 };
|
||||
|
||||
var colors = new[]
|
||||
{
|
||||
("#2196F3", "Primary"),
|
||||
("#4CAF50", "Success"),
|
||||
("#FF9800", "Warning"),
|
||||
("#F44336", "Danger"),
|
||||
("#9C27B0", "Purple")
|
||||
};
|
||||
|
||||
foreach (var (color, name) in colors)
|
||||
{
|
||||
var btn = new Button
|
||||
{
|
||||
Text = name,
|
||||
BackgroundColor = Color.FromArgb(color),
|
||||
TextColor = Colors.White,
|
||||
CornerRadius = 5
|
||||
};
|
||||
btn.Clicked += (s, e) => LogEvent($"{name} button clicked");
|
||||
layout.Children.Add(btn);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateButtonStates()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 10 };
|
||||
|
||||
var enabledBtn = new Button { Text = "Enabled Button", IsEnabled = true };
|
||||
enabledBtn.Clicked += (s, e) => LogEvent("Enabled button clicked");
|
||||
|
||||
var disabledBtn = new Button { Text = "Disabled Button", IsEnabled = false };
|
||||
|
||||
var toggleBtn = new Button { Text = "Toggle Above Button" };
|
||||
toggleBtn.Clicked += (s, e) =>
|
||||
{
|
||||
disabledBtn.IsEnabled = !disabledBtn.IsEnabled;
|
||||
disabledBtn.Text = disabledBtn.IsEnabled ? "Now Enabled!" : "Disabled Button";
|
||||
LogEvent($"Toggled button to: {(disabledBtn.IsEnabled ? "Enabled" : "Disabled")}");
|
||||
};
|
||||
|
||||
layout.Children.Add(enabledBtn);
|
||||
layout.Children.Add(disabledBtn);
|
||||
layout.Children.Add(toggleBtn);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateButtonVariations()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 10 };
|
||||
|
||||
var wideBtn = new Button
|
||||
{
|
||||
Text = "Wide Button",
|
||||
HorizontalOptions = LayoutOptions.Fill,
|
||||
BackgroundColor = Color.FromArgb("#673AB7"),
|
||||
TextColor = Colors.White
|
||||
};
|
||||
wideBtn.Clicked += (s, e) => LogEvent("Wide button clicked");
|
||||
|
||||
var tallBtn = new Button
|
||||
{
|
||||
Text = "Tall Button",
|
||||
HeightRequest = 60,
|
||||
BackgroundColor = Color.FromArgb("#009688"),
|
||||
TextColor = Colors.White
|
||||
};
|
||||
tallBtn.Clicked += (s, e) => LogEvent("Tall button clicked");
|
||||
|
||||
var roundBtn = new Button
|
||||
{
|
||||
Text = "Round",
|
||||
WidthRequest = 80,
|
||||
HeightRequest = 80,
|
||||
CornerRadius = 40,
|
||||
BackgroundColor = Color.FromArgb("#E91E63"),
|
||||
TextColor = Colors.White
|
||||
};
|
||||
roundBtn.Clicked += (s, e) => LogEvent("Round button clicked");
|
||||
|
||||
layout.Children.Add(wideBtn);
|
||||
layout.Children.Add(tallBtn);
|
||||
layout.Children.Add(new HorizontalStackLayout { Children = { roundBtn } });
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private Frame CreateSection(string title, View content)
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
CornerRadius = 8,
|
||||
Padding = new Thickness(15),
|
||||
BackgroundColor = Colors.White,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = title, FontSize = 16, FontAttributes = FontAttributes.Bold },
|
||||
content
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateEventLogPanel()
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5"),
|
||||
Padding = new Thickness(10),
|
||||
CornerRadius = 0,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "Event Log:", FontSize = 12, FontAttributes = FontAttributes.Bold },
|
||||
new ScrollView
|
||||
{
|
||||
HeightRequest = 80,
|
||||
Content = _eventLog
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void LogEvent(string message)
|
||||
{
|
||||
_eventCount++;
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
_eventLog.Text = $"[{timestamp}] {_eventCount}. {message}\n{_eventLog.Text}";
|
||||
}
|
||||
}
|
||||
150
ShellDemo/Pages/ButtonsPage.xaml
Normal file
150
ShellDemo/Pages/ButtonsPage.xaml
Normal file
@@ -0,0 +1,150 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.ButtonsPage"
|
||||
Title="Buttons Demo"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<Grid RowDefinitions="*,120">
|
||||
|
||||
<!-- Main Content -->
|
||||
<ScrollView Grid.Row="0">
|
||||
<VerticalStackLayout Padding="20" Spacing="20">
|
||||
|
||||
<Label Text="Button Styles & Events"
|
||||
FontSize="24"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Basic Buttons Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="Basic Buttons"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<Button x:Name="DefaultButton"
|
||||
Text="Default Button"
|
||||
Clicked="OnDefaultButtonClicked" />
|
||||
|
||||
<Button x:Name="TextButton"
|
||||
Text="Text Only"
|
||||
BackgroundColor="Transparent"
|
||||
TextColor="{StaticResource PrimaryColor}" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Styled Buttons Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="Styled Buttons"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Button Text="Primary"
|
||||
Style="{StaticResource PrimaryButton}"
|
||||
Clicked="OnStyledButtonClicked" />
|
||||
<Button Text="Success"
|
||||
Style="{StaticResource SuccessButton}"
|
||||
Clicked="OnStyledButtonClicked" />
|
||||
<Button Text="Warning"
|
||||
BackgroundColor="{StaticResource WarningColor}"
|
||||
TextColor="White"
|
||||
CornerRadius="5"
|
||||
Clicked="OnStyledButtonClicked" />
|
||||
<Button Text="Danger"
|
||||
Style="{StaticResource DangerButton}"
|
||||
Clicked="OnStyledButtonClicked" />
|
||||
<Button Text="Purple"
|
||||
BackgroundColor="{StaticResource PurpleColor}"
|
||||
TextColor="White"
|
||||
CornerRadius="5"
|
||||
Clicked="OnStyledButtonClicked" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Button States Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="Button States"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<Button x:Name="EnabledButton"
|
||||
Text="Enabled Button"
|
||||
IsEnabled="True"
|
||||
Clicked="OnEnabledButtonClicked" />
|
||||
|
||||
<Button x:Name="DisabledButton"
|
||||
Text="Disabled Button"
|
||||
IsEnabled="False" />
|
||||
|
||||
<Button x:Name="ToggleButton"
|
||||
Text="Toggle Above Button"
|
||||
Style="{StaticResource SecondaryButton}"
|
||||
Clicked="OnToggleButtonClicked" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Button Variations Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="Button Variations"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<Button Text="Wide Button"
|
||||
HorizontalOptions="Fill"
|
||||
BackgroundColor="#673AB7"
|
||||
TextColor="White"
|
||||
Clicked="OnVariationButtonClicked" />
|
||||
|
||||
<Button Text="Tall Button"
|
||||
HeightRequest="60"
|
||||
BackgroundColor="#009688"
|
||||
TextColor="White"
|
||||
Clicked="OnVariationButtonClicked" />
|
||||
|
||||
<HorizontalStackLayout>
|
||||
<Button Text="Round"
|
||||
WidthRequest="80"
|
||||
HeightRequest="80"
|
||||
CornerRadius="40"
|
||||
BackgroundColor="#E91E63"
|
||||
TextColor="White"
|
||||
Clicked="OnVariationButtonClicked" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- Event Log Panel -->
|
||||
<Border Grid.Row="1"
|
||||
BackgroundColor="{AppThemeBinding Light=#F5F5F5, Dark=#2C2C2C}"
|
||||
StrokeThickness="0"
|
||||
Padding="10">
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Event Log:"
|
||||
FontSize="12"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<ScrollView HeightRequest="80">
|
||||
<Label x:Name="EventLogLabel"
|
||||
Text="Events will appear here..."
|
||||
FontSize="11"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
LineBreakMode="WordWrap" />
|
||||
</ScrollView>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
55
ShellDemo/Pages/ButtonsPage.xaml.cs
Normal file
55
ShellDemo/Pages/ButtonsPage.xaml.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
// ButtonsPage - Comprehensive Button Control Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class ButtonsPage : ContentPage
|
||||
{
|
||||
private int _eventCount = 0;
|
||||
|
||||
public ButtonsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnDefaultButtonClicked(object? sender, EventArgs e)
|
||||
{
|
||||
LogEvent("Default Button clicked");
|
||||
}
|
||||
|
||||
private void OnStyledButtonClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (sender is Button btn)
|
||||
{
|
||||
LogEvent($"{btn.Text} button clicked");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnabledButtonClicked(object? sender, EventArgs e)
|
||||
{
|
||||
LogEvent("Enabled button clicked");
|
||||
}
|
||||
|
||||
private void OnToggleButtonClicked(object? sender, EventArgs e)
|
||||
{
|
||||
DisabledButton.IsEnabled = !DisabledButton.IsEnabled;
|
||||
DisabledButton.Text = DisabledButton.IsEnabled ? "Now Enabled!" : "Disabled Button";
|
||||
LogEvent($"Toggled button to: {(DisabledButton.IsEnabled ? "Enabled" : "Disabled")}");
|
||||
}
|
||||
|
||||
private void OnVariationButtonClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (sender is Button btn)
|
||||
{
|
||||
LogEvent($"{btn.Text} button clicked");
|
||||
}
|
||||
}
|
||||
|
||||
private void LogEvent(string message)
|
||||
{
|
||||
_eventCount++;
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
EventLogLabel.Text = $"[{timestamp}] {_eventCount}. {message}\n{EventLogLabel.Text}";
|
||||
}
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
// ControlsPage - Demonstrates various MAUI controls
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public class ControlsPage : ContentPage
|
||||
{
|
||||
public ControlsPage()
|
||||
{
|
||||
Title = "Controls";
|
||||
|
||||
Content = new ScrollView
|
||||
{
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = new Thickness(20),
|
||||
Spacing = 15,
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = "Control Gallery",
|
||||
FontSize = 24,
|
||||
FontAttributes = FontAttributes.Bold
|
||||
},
|
||||
|
||||
// Buttons
|
||||
CreateSection("Buttons", new View[]
|
||||
{
|
||||
CreateButtonRow()
|
||||
}),
|
||||
|
||||
// CheckBox & Switch
|
||||
CreateSection("Selection", new View[]
|
||||
{
|
||||
CreateCheckBoxRow(),
|
||||
CreateSwitchRow()
|
||||
}),
|
||||
|
||||
// Slider
|
||||
CreateSection("Slider", new View[]
|
||||
{
|
||||
CreateSliderRow()
|
||||
}),
|
||||
|
||||
// Picker
|
||||
CreateSection("Picker", new View[]
|
||||
{
|
||||
CreatePickerRow()
|
||||
}),
|
||||
|
||||
// Progress
|
||||
CreateSection("Progress", new View[]
|
||||
{
|
||||
CreateProgressRow()
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Frame CreateSection(string title, View[] content)
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 10 };
|
||||
layout.Children.Add(new Label
|
||||
{
|
||||
Text = title,
|
||||
FontSize = 18,
|
||||
FontAttributes = FontAttributes.Bold
|
||||
});
|
||||
|
||||
foreach (var view in content)
|
||||
{
|
||||
layout.Children.Add(view);
|
||||
}
|
||||
|
||||
return new Frame
|
||||
{
|
||||
CornerRadius = 8,
|
||||
Padding = new Thickness(15),
|
||||
BackgroundColor = Colors.White,
|
||||
Content = layout
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateButtonRow()
|
||||
{
|
||||
var resultLabel = new Label { TextColor = Colors.Gray, FontSize = 12 };
|
||||
|
||||
var layout = new VerticalStackLayout { Spacing = 10 };
|
||||
|
||||
var buttonRow = new HorizontalStackLayout { Spacing = 10 };
|
||||
|
||||
var primaryBtn = new Button { Text = "Primary", BackgroundColor = Color.FromArgb("#2196F3"), TextColor = Colors.White };
|
||||
primaryBtn.Clicked += (s, e) => resultLabel.Text = "Primary clicked!";
|
||||
|
||||
var successBtn = new Button { Text = "Success", BackgroundColor = Color.FromArgb("#4CAF50"), TextColor = Colors.White };
|
||||
successBtn.Clicked += (s, e) => resultLabel.Text = "Success clicked!";
|
||||
|
||||
var dangerBtn = new Button { Text = "Danger", BackgroundColor = Color.FromArgb("#F44336"), TextColor = Colors.White };
|
||||
dangerBtn.Clicked += (s, e) => resultLabel.Text = "Danger clicked!";
|
||||
|
||||
buttonRow.Children.Add(primaryBtn);
|
||||
buttonRow.Children.Add(successBtn);
|
||||
buttonRow.Children.Add(dangerBtn);
|
||||
|
||||
layout.Children.Add(buttonRow);
|
||||
layout.Children.Add(resultLabel);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateCheckBoxRow()
|
||||
{
|
||||
var layout = new HorizontalStackLayout { Spacing = 20 };
|
||||
|
||||
var cb1 = new CheckBox { IsChecked = true };
|
||||
var cb2 = new CheckBox { IsChecked = false };
|
||||
|
||||
layout.Children.Add(cb1);
|
||||
layout.Children.Add(new Label { Text = "Option 1", VerticalOptions = LayoutOptions.Center });
|
||||
layout.Children.Add(cb2);
|
||||
layout.Children.Add(new Label { Text = "Option 2", VerticalOptions = LayoutOptions.Center });
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateSwitchRow()
|
||||
{
|
||||
var label = new Label { Text = "Off", VerticalOptions = LayoutOptions.Center };
|
||||
var sw = new Switch { IsToggled = false };
|
||||
sw.Toggled += (s, e) => label.Text = e.Value ? "On" : "Off";
|
||||
|
||||
return new HorizontalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
Children = { sw, label }
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateSliderRow()
|
||||
{
|
||||
var label = new Label { Text = "Value: 50" };
|
||||
var slider = new Slider { Minimum = 0, Maximum = 100, Value = 50 };
|
||||
slider.ValueChanged += (s, e) => label.Text = $"Value: {(int)e.NewValue}";
|
||||
|
||||
return new VerticalStackLayout
|
||||
{
|
||||
Spacing = 5,
|
||||
Children = { slider, label }
|
||||
};
|
||||
}
|
||||
|
||||
private View CreatePickerRow()
|
||||
{
|
||||
var label = new Label { Text = "Selected: (none)", TextColor = Colors.Gray };
|
||||
var picker = new Picker { Title = "Select a fruit" };
|
||||
picker.Items.Add("Apple");
|
||||
picker.Items.Add("Banana");
|
||||
picker.Items.Add("Cherry");
|
||||
picker.Items.Add("Date");
|
||||
picker.Items.Add("Elderberry");
|
||||
|
||||
picker.SelectedIndexChanged += (s, e) =>
|
||||
{
|
||||
if (picker.SelectedIndex >= 0)
|
||||
label.Text = $"Selected: {picker.Items[picker.SelectedIndex]}";
|
||||
};
|
||||
|
||||
return new VerticalStackLayout
|
||||
{
|
||||
Spacing = 5,
|
||||
Children = { picker, label }
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateProgressRow()
|
||||
{
|
||||
var progress = new ProgressBar { Progress = 0.7 };
|
||||
var activity = new ActivityIndicator { IsRunning = true };
|
||||
|
||||
return new VerticalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
Children =
|
||||
{
|
||||
progress,
|
||||
new Label { Text = "70% Complete", FontSize = 12, TextColor = Colors.Gray },
|
||||
new HorizontalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
Children =
|
||||
{
|
||||
activity,
|
||||
new Label { Text = "Loading...", VerticalOptions = LayoutOptions.Center, TextColor = Colors.Gray }
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
132
ShellDemo/Pages/ControlsPage.xaml
Normal file
132
ShellDemo/Pages/ControlsPage.xaml
Normal file
@@ -0,0 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.ControlsPage"
|
||||
Title="Controls"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<ScrollView>
|
||||
<VerticalStackLayout Padding="20" Spacing="15">
|
||||
|
||||
<Label Text="Control Gallery"
|
||||
FontSize="24"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Buttons Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="Buttons"
|
||||
FontSize="18"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Button Text="Primary"
|
||||
Style="{StaticResource PrimaryButton}"
|
||||
Clicked="OnButtonClicked" />
|
||||
<Button Text="Success"
|
||||
Style="{StaticResource SuccessButton}"
|
||||
Clicked="OnButtonClicked" />
|
||||
<Button Text="Danger"
|
||||
Style="{StaticResource DangerButton}"
|
||||
Clicked="OnButtonClicked" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<Label x:Name="ButtonResultLabel"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Selection Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="Selection"
|
||||
FontSize="18"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- CheckBox Row -->
|
||||
<HorizontalStackLayout Spacing="20">
|
||||
<CheckBox x:Name="Checkbox1" IsChecked="True" />
|
||||
<Label Text="Option 1" VerticalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<CheckBox x:Name="Checkbox2" IsChecked="False" />
|
||||
<Label Text="Option 2" VerticalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<!-- Switch Row -->
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Switch x:Name="MainSwitch" IsToggled="False" Toggled="OnSwitchToggled" />
|
||||
<Label x:Name="SwitchLabel" Text="Off" VerticalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Slider Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="Slider"
|
||||
FontSize="18"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<Slider x:Name="MainSlider" Minimum="0" Maximum="100" Value="50" ValueChanged="OnSliderValueChanged" />
|
||||
<Label x:Name="SliderLabel" Text="Value: 50"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Picker Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="Picker"
|
||||
FontSize="18"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<Picker x:Name="MainPicker"
|
||||
Title="Select a fruit"
|
||||
SelectedIndexChanged="OnPickerSelectedIndexChanged">
|
||||
<Picker.ItemsSource>
|
||||
<x:Array Type="{x:Type x:String}">
|
||||
<x:String>Apple</x:String>
|
||||
<x:String>Banana</x:String>
|
||||
<x:String>Cherry</x:String>
|
||||
<x:String>Date</x:String>
|
||||
<x:String>Elderberry</x:String>
|
||||
</x:Array>
|
||||
</Picker.ItemsSource>
|
||||
</Picker>
|
||||
<Label x:Name="PickerLabel" Text="Selected: (none)"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Progress Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="Progress"
|
||||
FontSize="18"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<ProgressBar Progress="0.7" ProgressColor="{StaticResource PrimaryColor}" />
|
||||
<Label Text="70% Complete"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<ActivityIndicator IsRunning="True" Color="{StaticResource PrimaryColor}" />
|
||||
<Label Text="Loading..." VerticalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
||||
39
ShellDemo/Pages/ControlsPage.xaml.cs
Normal file
39
ShellDemo/Pages/ControlsPage.xaml.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
// ControlsPage - Demonstrates various MAUI controls
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class ControlsPage : ContentPage
|
||||
{
|
||||
public ControlsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnButtonClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (sender is Button btn)
|
||||
{
|
||||
ButtonResultLabel.Text = $"{btn.Text} clicked!";
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSwitchToggled(object? sender, ToggledEventArgs e)
|
||||
{
|
||||
SwitchLabel.Text = e.Value ? "On" : "Off";
|
||||
}
|
||||
|
||||
private void OnSliderValueChanged(object? sender, ValueChangedEventArgs e)
|
||||
{
|
||||
SliderLabel.Text = $"Value: {(int)e.NewValue}";
|
||||
}
|
||||
|
||||
private void OnPickerSelectedIndexChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (MainPicker.SelectedIndex >= 0)
|
||||
{
|
||||
PickerLabel.Text = $"Selected: {MainPicker.ItemsSource[MainPicker.SelectedIndex]}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
// DetailPage - Demonstrates push/pop navigation
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
/// <summary>
|
||||
/// A detail page that can be pushed onto the navigation stack.
|
||||
/// </summary>
|
||||
public class DetailPage : ContentPage
|
||||
{
|
||||
private readonly string _itemName;
|
||||
|
||||
public DetailPage() : this("Detail Item")
|
||||
{
|
||||
}
|
||||
|
||||
public DetailPage(string itemName)
|
||||
{
|
||||
_itemName = itemName;
|
||||
Title = "Detail Page";
|
||||
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = new Thickness(30),
|
||||
Spacing = 20,
|
||||
VerticalOptions = LayoutOptions.Center,
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = "Pushed Page",
|
||||
FontSize = 28,
|
||||
FontAttributes = FontAttributes.Bold,
|
||||
HorizontalOptions = LayoutOptions.Center,
|
||||
TextColor = Color.FromArgb("#9C27B0")
|
||||
},
|
||||
|
||||
new Label
|
||||
{
|
||||
Text = $"You navigated to: {_itemName}",
|
||||
FontSize = 16,
|
||||
HorizontalOptions = LayoutOptions.Center
|
||||
},
|
||||
|
||||
new Label
|
||||
{
|
||||
Text = "This page was pushed onto the navigation stack using Shell.Current.GoToAsync()",
|
||||
FontSize = 14,
|
||||
TextColor = Colors.Gray,
|
||||
HorizontalTextAlignment = TextAlignment.Center,
|
||||
LineBreakMode = LineBreakMode.WordWrap
|
||||
},
|
||||
|
||||
new BoxView
|
||||
{
|
||||
HeightRequest = 2,
|
||||
Color = Color.FromArgb("#E0E0E0"),
|
||||
Margin = new Thickness(0, 20)
|
||||
},
|
||||
|
||||
CreateBackButton(),
|
||||
|
||||
new Label
|
||||
{
|
||||
Text = "Use the back button above or the hardware/gesture back to pop this page",
|
||||
FontSize = 12,
|
||||
TextColor = Colors.Gray,
|
||||
HorizontalTextAlignment = TextAlignment.Center,
|
||||
Margin = new Thickness(0, 20, 0, 0)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Button CreateBackButton()
|
||||
{
|
||||
var backBtn = new Button
|
||||
{
|
||||
Text = "Go Back (Pop)",
|
||||
BackgroundColor = Color.FromArgb("#9C27B0"),
|
||||
TextColor = Colors.White,
|
||||
HorizontalOptions = LayoutOptions.Center,
|
||||
Padding = new Thickness(30, 10)
|
||||
};
|
||||
|
||||
backBtn.Clicked += (s, e) =>
|
||||
{
|
||||
// Pop this page off the navigation stack using LinuxViewRenderer
|
||||
Console.WriteLine("[DetailPage] Go Back clicked");
|
||||
var success = LinuxViewRenderer.PopPage();
|
||||
Console.WriteLine($"[DetailPage] PopPage result: {success}");
|
||||
};
|
||||
|
||||
return backBtn;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query property for passing data to DetailPage.
|
||||
/// </summary>
|
||||
[QueryProperty(nameof(ItemName), "item")]
|
||||
public class DetailPageWithQuery : DetailPage
|
||||
{
|
||||
private string _itemName = "Item";
|
||||
|
||||
public string ItemName
|
||||
{
|
||||
get => _itemName;
|
||||
set
|
||||
{
|
||||
_itemName = value;
|
||||
// Update the title when the property is set
|
||||
Title = $"Detail: {value}";
|
||||
}
|
||||
}
|
||||
|
||||
public DetailPageWithQuery() : base()
|
||||
{
|
||||
}
|
||||
}
|
||||
48
ShellDemo/Pages/DetailPage.xaml
Normal file
48
ShellDemo/Pages/DetailPage.xaml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.DetailPage"
|
||||
Title="Detail Page"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<VerticalStackLayout Padding="30"
|
||||
Spacing="20"
|
||||
VerticalOptions="Center">
|
||||
|
||||
<Label Text="Pushed Page"
|
||||
FontSize="28"
|
||||
FontAttributes="Bold"
|
||||
HorizontalOptions="Center"
|
||||
TextColor="{StaticResource PurpleColor}" />
|
||||
|
||||
<Label x:Name="ItemNameLabel"
|
||||
Text="You navigated to: Detail Item"
|
||||
FontSize="16"
|
||||
HorizontalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<Label Text="This page was pushed onto the navigation stack using Shell.Current.GoToAsync()"
|
||||
FontSize="14"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
HorizontalTextAlignment="Center"
|
||||
LineBreakMode="WordWrap" />
|
||||
|
||||
<BoxView Style="{StaticResource ThemedDivider}" Margin="0,20" />
|
||||
|
||||
<Button x:Name="BackButton"
|
||||
Text="Go Back (Pop)"
|
||||
BackgroundColor="{StaticResource PurpleColor}"
|
||||
TextColor="White"
|
||||
HorizontalOptions="Center"
|
||||
Padding="30,10"
|
||||
CornerRadius="5"
|
||||
Clicked="OnBackClicked" />
|
||||
|
||||
<Label Text="Use the back button above or the hardware/gesture back to pop this page"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
HorizontalTextAlignment="Center"
|
||||
Margin="0,20,0,0" />
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ContentPage>
|
||||
55
ShellDemo/Pages/DetailPage.xaml.cs
Normal file
55
ShellDemo/Pages/DetailPage.xaml.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
// DetailPage - Demonstrates push/pop navigation
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
/// <summary>
|
||||
/// A detail page that can be pushed onto the navigation stack.
|
||||
/// </summary>
|
||||
public partial class DetailPage : ContentPage
|
||||
{
|
||||
private readonly string _itemName;
|
||||
|
||||
public DetailPage() : this("Detail Item")
|
||||
{
|
||||
}
|
||||
|
||||
public DetailPage(string itemName)
|
||||
{
|
||||
_itemName = itemName;
|
||||
InitializeComponent();
|
||||
ItemNameLabel.Text = $"You navigated to: {_itemName}";
|
||||
}
|
||||
|
||||
private void OnBackClicked(object? sender, EventArgs e)
|
||||
{
|
||||
Console.WriteLine("[DetailPage] Go Back clicked");
|
||||
var success = LinuxViewRenderer.PopPage();
|
||||
Console.WriteLine($"[DetailPage] PopPage result: {success}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Query property for passing data to DetailPage.
|
||||
/// </summary>
|
||||
[QueryProperty(nameof(ItemName), "item")]
|
||||
public class DetailPageWithQuery : DetailPage
|
||||
{
|
||||
private string _itemName = "Item";
|
||||
|
||||
public string ItemName
|
||||
{
|
||||
get => _itemName;
|
||||
set
|
||||
{
|
||||
_itemName = value;
|
||||
Title = $"Detail: {value}";
|
||||
}
|
||||
}
|
||||
|
||||
public DetailPageWithQuery() : base()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,594 +0,0 @@
|
||||
// GridsPage - Demonstrates Grid layouts with various options
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public class GridsPage : ContentPage
|
||||
{
|
||||
public GridsPage()
|
||||
{
|
||||
Title = "Grids";
|
||||
|
||||
Content = new ScrollView
|
||||
{
|
||||
Orientation = ScrollOrientation.Both,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 25,
|
||||
Children =
|
||||
{
|
||||
CreateSectionHeader("Basic Grid (2x2)"),
|
||||
CreateBasicGrid(),
|
||||
|
||||
CreateSectionHeader("Column Definitions"),
|
||||
CreateColumnDefinitionsDemo(),
|
||||
|
||||
CreateSectionHeader("Row Definitions"),
|
||||
CreateRowDefinitionsDemo(),
|
||||
|
||||
CreateSectionHeader("Auto Rows (Empty vs Content)"),
|
||||
CreateAutoRowsDemo(),
|
||||
|
||||
CreateSectionHeader("Star Sizing (Proportional)"),
|
||||
CreateStarSizingDemo(),
|
||||
|
||||
CreateSectionHeader("Row & Column Spacing"),
|
||||
CreateSpacingDemo(),
|
||||
|
||||
CreateSectionHeader("Row & Column Span"),
|
||||
CreateSpanDemo(),
|
||||
|
||||
CreateSectionHeader("Mixed Sizing"),
|
||||
CreateMixedSizingDemo(),
|
||||
|
||||
CreateSectionHeader("Nested Grids"),
|
||||
CreateNestedGridDemo(),
|
||||
|
||||
new BoxView { HeightRequest = 20 } // Bottom padding
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Label CreateSectionHeader(string text)
|
||||
{
|
||||
return new Label
|
||||
{
|
||||
Text = text,
|
||||
FontSize = 18,
|
||||
FontAttributes = FontAttributes.Bold,
|
||||
TextColor = Color.FromArgb("#2196F3"),
|
||||
Margin = new Thickness(0, 10, 0, 5)
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateBasicGrid()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
},
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5")
|
||||
};
|
||||
|
||||
var cell1 = CreateCell("Row 0, Col 0", "#E3F2FD");
|
||||
var cell2 = CreateCell("Row 0, Col 1", "#E8F5E9");
|
||||
var cell3 = CreateCell("Row 1, Col 0", "#FFF3E0");
|
||||
var cell4 = CreateCell("Row 1, Col 1", "#FCE4EC");
|
||||
|
||||
Grid.SetRow(cell1, 0); Grid.SetColumn(cell1, 0);
|
||||
Grid.SetRow(cell2, 0); Grid.SetColumn(cell2, 1);
|
||||
Grid.SetRow(cell3, 1); Grid.SetColumn(cell3, 0);
|
||||
Grid.SetRow(cell4, 1); Grid.SetColumn(cell4, 1);
|
||||
|
||||
grid.Children.Add(cell1);
|
||||
grid.Children.Add(cell2);
|
||||
grid.Children.Add(cell3);
|
||||
grid.Children.Add(cell4);
|
||||
|
||||
return CreateDemoContainer(grid, "Equal columns using Star sizing");
|
||||
}
|
||||
|
||||
private View CreateColumnDefinitionsDemo()
|
||||
{
|
||||
var stack = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Auto width columns
|
||||
var autoGrid = new Grid
|
||||
{
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Auto },
|
||||
new ColumnDefinition { Width = GridLength.Auto },
|
||||
new ColumnDefinition { Width = GridLength.Auto }
|
||||
},
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5")
|
||||
};
|
||||
|
||||
var a1 = CreateCell("Auto", "#BBDEFB");
|
||||
var a2 = CreateCell("Auto Width", "#C8E6C9");
|
||||
var a3 = CreateCell("A", "#FFECB3");
|
||||
Grid.SetColumn(a1, 0);
|
||||
Grid.SetColumn(a2, 1);
|
||||
Grid.SetColumn(a3, 2);
|
||||
autoGrid.Children.Add(a1);
|
||||
autoGrid.Children.Add(a2);
|
||||
autoGrid.Children.Add(a3);
|
||||
|
||||
stack.Children.Add(new Label { Text = "Auto: Sizes to content", FontSize = 12, TextColor = Colors.Gray });
|
||||
stack.Children.Add(autoGrid);
|
||||
|
||||
// Absolute width columns
|
||||
var absoluteGrid = new Grid
|
||||
{
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(50) },
|
||||
new ColumnDefinition { Width = new GridLength(100) },
|
||||
new ColumnDefinition { Width = new GridLength(150) }
|
||||
},
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5")
|
||||
};
|
||||
|
||||
var b1 = CreateCell("50px", "#BBDEFB");
|
||||
var b2 = CreateCell("100px", "#C8E6C9");
|
||||
var b3 = CreateCell("150px", "#FFECB3");
|
||||
Grid.SetColumn(b1, 0);
|
||||
Grid.SetColumn(b2, 1);
|
||||
Grid.SetColumn(b3, 2);
|
||||
absoluteGrid.Children.Add(b1);
|
||||
absoluteGrid.Children.Add(b2);
|
||||
absoluteGrid.Children.Add(b3);
|
||||
|
||||
stack.Children.Add(new Label { Text = "Absolute: Fixed pixel widths (50, 100, 150)", FontSize = 12, TextColor = Colors.Gray, Margin = new Thickness(0, 10, 0, 0) });
|
||||
stack.Children.Add(absoluteGrid);
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
private View CreateRowDefinitionsDemo()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
WidthRequest = 200,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = new GridLength(30) },
|
||||
new RowDefinition { Height = new GridLength(50) },
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = new GridLength(40) }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
},
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5")
|
||||
};
|
||||
|
||||
var r1 = CreateCell("30px height", "#BBDEFB");
|
||||
var r2 = CreateCell("50px height", "#C8E6C9");
|
||||
var r3 = CreateCell("Auto height\n(fits content)", "#FFECB3");
|
||||
var r4 = CreateCell("40px height", "#F8BBD9");
|
||||
|
||||
Grid.SetRow(r1, 0);
|
||||
Grid.SetRow(r2, 1);
|
||||
Grid.SetRow(r3, 2);
|
||||
Grid.SetRow(r4, 3);
|
||||
|
||||
grid.Children.Add(r1);
|
||||
grid.Children.Add(r2);
|
||||
grid.Children.Add(r3);
|
||||
grid.Children.Add(r4);
|
||||
|
||||
return CreateDemoContainer(grid, "Different row heights: 30px, 50px, Auto, 40px");
|
||||
}
|
||||
|
||||
private View CreateAutoRowsDemo()
|
||||
{
|
||||
var stack = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Grid with empty Auto row
|
||||
var emptyAutoGrid = new Grid
|
||||
{
|
||||
WidthRequest = 250,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = new GridLength(40) },
|
||||
new RowDefinition { Height = GridLength.Auto }, // Empty - should collapse
|
||||
new RowDefinition { Height = new GridLength(40) }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
},
|
||||
BackgroundColor = Color.FromArgb("#E0E0E0")
|
||||
};
|
||||
|
||||
var r1 = CreateCell("Row 0: 40px", "#BBDEFB");
|
||||
// Row 1 is Auto with NO content - should be 0 height
|
||||
var r3 = CreateCell("Row 2: 40px", "#C8E6C9");
|
||||
|
||||
Grid.SetRow(r1, 0);
|
||||
Grid.SetRow(r3, 2); // Skip row 1
|
||||
|
||||
emptyAutoGrid.Children.Add(r1);
|
||||
emptyAutoGrid.Children.Add(r3);
|
||||
|
||||
stack.Children.Add(new Label { Text = "Empty Auto row (Row 1) should collapse to 0 height:", FontSize = 12, TextColor = Colors.Gray });
|
||||
stack.Children.Add(emptyAutoGrid);
|
||||
|
||||
// Grid with Auto row that has content
|
||||
var contentAutoGrid = new Grid
|
||||
{
|
||||
WidthRequest = 250,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = new GridLength(40) },
|
||||
new RowDefinition { Height = GridLength.Auto }, // Has content
|
||||
new RowDefinition { Height = new GridLength(40) }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
},
|
||||
BackgroundColor = Color.FromArgb("#E0E0E0")
|
||||
};
|
||||
|
||||
var c1 = CreateCell("Row 0: 40px", "#BBDEFB");
|
||||
var c2 = CreateCell("Row 1: Auto (sized to this content)", "#FFECB3");
|
||||
var c3 = CreateCell("Row 2: 40px", "#C8E6C9");
|
||||
|
||||
Grid.SetRow(c1, 0);
|
||||
Grid.SetRow(c2, 1);
|
||||
Grid.SetRow(c3, 2);
|
||||
|
||||
contentAutoGrid.Children.Add(c1);
|
||||
contentAutoGrid.Children.Add(c2);
|
||||
contentAutoGrid.Children.Add(c3);
|
||||
|
||||
stack.Children.Add(new Label { Text = "Auto row with content sizes to fit:", FontSize = 12, TextColor = Colors.Gray, Margin = new Thickness(0, 10, 0, 0) });
|
||||
stack.Children.Add(contentAutoGrid);
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
private View CreateStarSizingDemo()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
|
||||
new ColumnDefinition { Width = new GridLength(2, GridUnitType.Star) },
|
||||
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
|
||||
},
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5")
|
||||
};
|
||||
|
||||
var s1 = CreateCell("1*", "#BBDEFB");
|
||||
var s2 = CreateCell("2* (double)", "#C8E6C9");
|
||||
var s3 = CreateCell("1*", "#FFECB3");
|
||||
|
||||
Grid.SetColumn(s1, 0);
|
||||
Grid.SetColumn(s2, 1);
|
||||
Grid.SetColumn(s3, 2);
|
||||
|
||||
grid.Children.Add(s1);
|
||||
grid.Children.Add(s2);
|
||||
grid.Children.Add(s3);
|
||||
|
||||
return CreateDemoContainer(grid, "Star proportions: 1* | 2* | 1* = 25% | 50% | 25%");
|
||||
}
|
||||
|
||||
private View CreateSpacingDemo()
|
||||
{
|
||||
var stack = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// No spacing
|
||||
var noSpacing = new Grid
|
||||
{
|
||||
RowSpacing = 0,
|
||||
ColumnSpacing = 0,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
AddFourCells(noSpacing);
|
||||
stack.Children.Add(new Label { Text = "No spacing (RowSpacing=0, ColumnSpacing=0)", FontSize = 12, TextColor = Colors.Gray });
|
||||
stack.Children.Add(noSpacing);
|
||||
|
||||
// With spacing
|
||||
var withSpacing = new Grid
|
||||
{
|
||||
RowSpacing = 10,
|
||||
ColumnSpacing = 10,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
AddFourCells(withSpacing);
|
||||
stack.Children.Add(new Label { Text = "With spacing (RowSpacing=10, ColumnSpacing=10)", FontSize = 12, TextColor = Colors.Gray, Margin = new Thickness(0, 10, 0, 0) });
|
||||
stack.Children.Add(withSpacing);
|
||||
|
||||
// Different row/column spacing
|
||||
var mixedSpacing = new Grid
|
||||
{
|
||||
RowSpacing = 5,
|
||||
ColumnSpacing = 20,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
AddFourCells(mixedSpacing);
|
||||
stack.Children.Add(new Label { Text = "Mixed spacing (RowSpacing=5, ColumnSpacing=20)", FontSize = 12, TextColor = Colors.Gray, Margin = new Thickness(0, 10, 0, 0) });
|
||||
stack.Children.Add(mixedSpacing);
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
private View CreateSpanDemo()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
RowSpacing = 5,
|
||||
ColumnSpacing = 5,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
|
||||
// Spanning header
|
||||
var header = CreateCell("ColumnSpan=3 (Header)", "#1976D2", Colors.White);
|
||||
Grid.SetRow(header, 0);
|
||||
Grid.SetColumn(header, 0);
|
||||
Grid.SetColumnSpan(header, 3);
|
||||
|
||||
// Left sidebar spanning 2 rows
|
||||
var sidebar = CreateCell("RowSpan=2\n(Sidebar)", "#388E3C", Colors.White);
|
||||
Grid.SetRow(sidebar, 1);
|
||||
Grid.SetColumn(sidebar, 0);
|
||||
Grid.SetRowSpan(sidebar, 2);
|
||||
|
||||
// Content cells
|
||||
var content1 = CreateCell("Content 1", "#E3F2FD");
|
||||
Grid.SetRow(content1, 1);
|
||||
Grid.SetColumn(content1, 1);
|
||||
|
||||
var content2 = CreateCell("Content 2", "#E8F5E9");
|
||||
Grid.SetRow(content2, 1);
|
||||
Grid.SetColumn(content2, 2);
|
||||
|
||||
var content3 = CreateCell("Content 3", "#FFF3E0");
|
||||
Grid.SetRow(content3, 2);
|
||||
Grid.SetColumn(content3, 1);
|
||||
|
||||
var content4 = CreateCell("Content 4", "#FCE4EC");
|
||||
Grid.SetRow(content4, 2);
|
||||
Grid.SetColumn(content4, 2);
|
||||
|
||||
grid.Children.Add(header);
|
||||
grid.Children.Add(sidebar);
|
||||
grid.Children.Add(content1);
|
||||
grid.Children.Add(content2);
|
||||
grid.Children.Add(content3);
|
||||
grid.Children.Add(content4);
|
||||
|
||||
return CreateDemoContainer(grid, "Header spans 3 columns, Sidebar spans 2 rows");
|
||||
}
|
||||
|
||||
private View CreateMixedSizingDemo()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
ColumnSpacing = 5,
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(60) }, // Fixed
|
||||
new ColumnDefinition { Width = GridLength.Star }, // Fill
|
||||
new ColumnDefinition { Width = GridLength.Auto }, // Auto
|
||||
new ColumnDefinition { Width = new GridLength(60) } // Fixed
|
||||
},
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5")
|
||||
};
|
||||
|
||||
var c1 = CreateCell("60px", "#BBDEFB");
|
||||
var c2 = CreateCell("Star (fills remaining)", "#C8E6C9");
|
||||
var c3 = CreateCell("Auto", "#FFECB3");
|
||||
var c4 = CreateCell("60px", "#F8BBD9");
|
||||
|
||||
Grid.SetColumn(c1, 0);
|
||||
Grid.SetColumn(c2, 1);
|
||||
Grid.SetColumn(c3, 2);
|
||||
Grid.SetColumn(c4, 3);
|
||||
|
||||
grid.Children.Add(c1);
|
||||
grid.Children.Add(c2);
|
||||
grid.Children.Add(c3);
|
||||
grid.Children.Add(c4);
|
||||
|
||||
return CreateDemoContainer(grid, "Mixed: 60px | Star | Auto | 60px");
|
||||
}
|
||||
|
||||
private View CreateNestedGridDemo()
|
||||
{
|
||||
var outerGrid = new Grid
|
||||
{
|
||||
RowSpacing = 10,
|
||||
ColumnSpacing = 10,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
},
|
||||
BackgroundColor = Color.FromArgb("#E0E0E0"),
|
||||
Padding = new Thickness(10)
|
||||
};
|
||||
|
||||
// Nested grid 1
|
||||
var innerGrid1 = new Grid
|
||||
{
|
||||
RowSpacing = 2,
|
||||
ColumnSpacing = 2,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
var i1a = CreateCell("A", "#BBDEFB", null, 8);
|
||||
var i1b = CreateCell("B", "#90CAF9", null, 8);
|
||||
var i1c = CreateCell("C", "#64B5F6", null, 8);
|
||||
var i1d = CreateCell("D", "#42A5F5", null, 8);
|
||||
Grid.SetRow(i1a, 0); Grid.SetColumn(i1a, 0);
|
||||
Grid.SetRow(i1b, 0); Grid.SetColumn(i1b, 1);
|
||||
Grid.SetRow(i1c, 1); Grid.SetColumn(i1c, 0);
|
||||
Grid.SetRow(i1d, 1); Grid.SetColumn(i1d, 1);
|
||||
innerGrid1.Children.Add(i1a);
|
||||
innerGrid1.Children.Add(i1b);
|
||||
innerGrid1.Children.Add(i1c);
|
||||
innerGrid1.Children.Add(i1d);
|
||||
|
||||
// Nested grid 2
|
||||
var innerGrid2 = new Grid
|
||||
{
|
||||
RowSpacing = 2,
|
||||
ColumnSpacing = 2,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
var i2a = CreateCell("1", "#C8E6C9", null, 8);
|
||||
var i2b = CreateCell("2", "#A5D6A7", null, 8);
|
||||
var i2c = CreateCell("3", "#81C784", null, 8);
|
||||
var i2d = CreateCell("4", "#66BB6A", null, 8);
|
||||
Grid.SetRow(i2a, 0); Grid.SetColumn(i2a, 0);
|
||||
Grid.SetRow(i2b, 0); Grid.SetColumn(i2b, 1);
|
||||
Grid.SetRow(i2c, 1); Grid.SetColumn(i2c, 0);
|
||||
Grid.SetRow(i2d, 1); Grid.SetColumn(i2d, 1);
|
||||
innerGrid2.Children.Add(i2a);
|
||||
innerGrid2.Children.Add(i2b);
|
||||
innerGrid2.Children.Add(i2c);
|
||||
innerGrid2.Children.Add(i2d);
|
||||
|
||||
Grid.SetRow(innerGrid1, 0); Grid.SetColumn(innerGrid1, 0);
|
||||
Grid.SetRow(innerGrid2, 0); Grid.SetColumn(innerGrid2, 1);
|
||||
|
||||
var label1 = new Label { Text = "Outer Grid Row 1", HorizontalOptions = LayoutOptions.Center };
|
||||
var label2 = new Label { Text = "Spans both columns", HorizontalOptions = LayoutOptions.Center };
|
||||
Grid.SetRow(label1, 1); Grid.SetColumn(label1, 0);
|
||||
Grid.SetRow(label2, 1); Grid.SetColumn(label2, 1);
|
||||
|
||||
outerGrid.Children.Add(innerGrid1);
|
||||
outerGrid.Children.Add(innerGrid2);
|
||||
outerGrid.Children.Add(label1);
|
||||
outerGrid.Children.Add(label2);
|
||||
|
||||
return CreateDemoContainer(outerGrid, "Outer grid contains two nested 2x2 grids");
|
||||
}
|
||||
|
||||
private Border CreateCell(string text, string bgColor, Color? textColor = null, float fontSize = 12)
|
||||
{
|
||||
return new Border
|
||||
{
|
||||
BackgroundColor = Color.FromArgb(bgColor),
|
||||
Padding = new Thickness(10, 8),
|
||||
StrokeThickness = 0,
|
||||
Content = new Label
|
||||
{
|
||||
Text = text,
|
||||
FontSize = fontSize,
|
||||
TextColor = textColor ?? Colors.Black,
|
||||
HorizontalTextAlignment = TextAlignment.Center,
|
||||
VerticalTextAlignment = TextAlignment.Center
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void AddFourCells(Grid grid)
|
||||
{
|
||||
var c1 = CreateCell("0,0", "#BBDEFB");
|
||||
var c2 = CreateCell("0,1", "#C8E6C9");
|
||||
var c3 = CreateCell("1,0", "#FFECB3");
|
||||
var c4 = CreateCell("1,1", "#F8BBD9");
|
||||
|
||||
Grid.SetRow(c1, 0); Grid.SetColumn(c1, 0);
|
||||
Grid.SetRow(c2, 0); Grid.SetColumn(c2, 1);
|
||||
Grid.SetRow(c3, 1); Grid.SetColumn(c3, 0);
|
||||
Grid.SetRow(c4, 1); Grid.SetColumn(c4, 1);
|
||||
|
||||
grid.Children.Add(c1);
|
||||
grid.Children.Add(c2);
|
||||
grid.Children.Add(c3);
|
||||
grid.Children.Add(c4);
|
||||
}
|
||||
|
||||
private View CreateDemoContainer(View content, string description)
|
||||
{
|
||||
return new VerticalStackLayout
|
||||
{
|
||||
Spacing = 5,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = description, FontSize = 12, TextColor = Colors.Gray },
|
||||
content
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
13
ShellDemo/Pages/GridsPage.xaml
Normal file
13
ShellDemo/Pages/GridsPage.xaml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.GridsPage"
|
||||
Title="Grids"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<ScrollView Orientation="Both">
|
||||
<VerticalStackLayout x:Name="MainContent" Spacing="25" Padding="20">
|
||||
<!-- Content will be added dynamically with proper theming -->
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
||||
431
ShellDemo/Pages/GridsPage.xaml.cs
Normal file
431
ShellDemo/Pages/GridsPage.xaml.cs
Normal file
@@ -0,0 +1,431 @@
|
||||
// GridsPage - Demonstrates Grid layouts with various options
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class GridsPage : ContentPage
|
||||
{
|
||||
public GridsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
BuildContent();
|
||||
}
|
||||
|
||||
private void BuildContent()
|
||||
{
|
||||
MainContent.Children.Add(CreateSectionHeader("Basic Grid (2x2)"));
|
||||
MainContent.Children.Add(CreateBasicGrid());
|
||||
|
||||
MainContent.Children.Add(CreateSectionHeader("Column Definitions"));
|
||||
MainContent.Children.Add(CreateColumnDefinitionsDemo());
|
||||
|
||||
MainContent.Children.Add(CreateSectionHeader("Row Definitions"));
|
||||
MainContent.Children.Add(CreateRowDefinitionsDemo());
|
||||
|
||||
MainContent.Children.Add(CreateSectionHeader("Star Sizing (Proportional)"));
|
||||
MainContent.Children.Add(CreateStarSizingDemo());
|
||||
|
||||
MainContent.Children.Add(CreateSectionHeader("Row & Column Spacing"));
|
||||
MainContent.Children.Add(CreateSpacingDemo());
|
||||
|
||||
MainContent.Children.Add(CreateSectionHeader("Row & Column Span"));
|
||||
MainContent.Children.Add(CreateSpanDemo());
|
||||
|
||||
MainContent.Children.Add(CreateSectionHeader("Mixed Sizing"));
|
||||
MainContent.Children.Add(CreateMixedSizingDemo());
|
||||
|
||||
MainContent.Children.Add(new BoxView { HeightRequest = 20 });
|
||||
}
|
||||
|
||||
private Label CreateSectionHeader(string text)
|
||||
{
|
||||
var label = new Label
|
||||
{
|
||||
Text = text,
|
||||
FontSize = 18,
|
||||
FontAttributes = FontAttributes.Bold,
|
||||
Margin = new Thickness(0, 10, 0, 5)
|
||||
};
|
||||
label.SetAppThemeColor(Label.TextColorProperty,
|
||||
Color.FromArgb("#2196F3"),
|
||||
Color.FromArgb("#64B5F6"));
|
||||
return label;
|
||||
}
|
||||
|
||||
private View CreateBasicGrid()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
grid.SetAppThemeColor(Grid.BackgroundColorProperty,
|
||||
Color.FromArgb("#F5F5F5"),
|
||||
Color.FromArgb("#2C2C2C"));
|
||||
|
||||
var cell1 = CreateCell("Row 0, Col 0", "#E3F2FD", "#1A3A5C");
|
||||
var cell2 = CreateCell("Row 0, Col 1", "#E8F5E9", "#1A3C1A");
|
||||
var cell3 = CreateCell("Row 1, Col 0", "#FFF3E0", "#3C2A1A");
|
||||
var cell4 = CreateCell("Row 1, Col 1", "#FCE4EC", "#3C1A2A");
|
||||
|
||||
Grid.SetRow(cell1, 0); Grid.SetColumn(cell1, 0);
|
||||
Grid.SetRow(cell2, 0); Grid.SetColumn(cell2, 1);
|
||||
Grid.SetRow(cell3, 1); Grid.SetColumn(cell3, 0);
|
||||
Grid.SetRow(cell4, 1); Grid.SetColumn(cell4, 1);
|
||||
|
||||
grid.Children.Add(cell1);
|
||||
grid.Children.Add(cell2);
|
||||
grid.Children.Add(cell3);
|
||||
grid.Children.Add(cell4);
|
||||
|
||||
return CreateDemoContainer(grid, "Equal columns using Star sizing");
|
||||
}
|
||||
|
||||
private View CreateColumnDefinitionsDemo()
|
||||
{
|
||||
var stack = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Auto width columns
|
||||
var autoGrid = new Grid
|
||||
{
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Auto },
|
||||
new ColumnDefinition { Width = GridLength.Auto },
|
||||
new ColumnDefinition { Width = GridLength.Auto }
|
||||
}
|
||||
};
|
||||
autoGrid.SetAppThemeColor(Grid.BackgroundColorProperty,
|
||||
Color.FromArgb("#F5F5F5"),
|
||||
Color.FromArgb("#2C2C2C"));
|
||||
|
||||
var a1 = CreateCell("Auto", "#BBDEFB", "#1A3A5C");
|
||||
var a2 = CreateCell("Auto Width", "#C8E6C9", "#1A3C1A");
|
||||
var a3 = CreateCell("A", "#FFECB3", "#3C3A1A");
|
||||
Grid.SetColumn(a1, 0);
|
||||
Grid.SetColumn(a2, 1);
|
||||
Grid.SetColumn(a3, 2);
|
||||
autoGrid.Children.Add(a1);
|
||||
autoGrid.Children.Add(a2);
|
||||
autoGrid.Children.Add(a3);
|
||||
|
||||
var autoLabel = new Label { Text = "Auto: Sizes to content", FontSize = 12 };
|
||||
autoLabel.SetAppThemeColor(Label.TextColorProperty,
|
||||
Color.FromArgb("#757575"),
|
||||
Color.FromArgb("#B0B0B0"));
|
||||
stack.Children.Add(autoLabel);
|
||||
stack.Children.Add(autoGrid);
|
||||
|
||||
// Absolute width columns
|
||||
var absoluteGrid = new Grid
|
||||
{
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(50) },
|
||||
new ColumnDefinition { Width = new GridLength(100) },
|
||||
new ColumnDefinition { Width = new GridLength(150) }
|
||||
}
|
||||
};
|
||||
absoluteGrid.SetAppThemeColor(Grid.BackgroundColorProperty,
|
||||
Color.FromArgb("#F5F5F5"),
|
||||
Color.FromArgb("#2C2C2C"));
|
||||
|
||||
var b1 = CreateCell("50px", "#BBDEFB", "#1A3A5C");
|
||||
var b2 = CreateCell("100px", "#C8E6C9", "#1A3C1A");
|
||||
var b3 = CreateCell("150px", "#FFECB3", "#3C3A1A");
|
||||
Grid.SetColumn(b1, 0);
|
||||
Grid.SetColumn(b2, 1);
|
||||
Grid.SetColumn(b3, 2);
|
||||
absoluteGrid.Children.Add(b1);
|
||||
absoluteGrid.Children.Add(b2);
|
||||
absoluteGrid.Children.Add(b3);
|
||||
|
||||
var absLabel = new Label { Text = "Absolute: Fixed pixel widths (50, 100, 150)", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) };
|
||||
absLabel.SetAppThemeColor(Label.TextColorProperty,
|
||||
Color.FromArgb("#757575"),
|
||||
Color.FromArgb("#B0B0B0"));
|
||||
stack.Children.Add(absLabel);
|
||||
stack.Children.Add(absoluteGrid);
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
private View CreateRowDefinitionsDemo()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
WidthRequest = 200,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = new GridLength(30) },
|
||||
new RowDefinition { Height = new GridLength(50) },
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = new GridLength(40) }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
grid.SetAppThemeColor(Grid.BackgroundColorProperty,
|
||||
Color.FromArgb("#F5F5F5"),
|
||||
Color.FromArgb("#2C2C2C"));
|
||||
|
||||
var r1 = CreateCell("30px height", "#BBDEFB", "#1A3A5C");
|
||||
var r2 = CreateCell("50px height", "#C8E6C9", "#1A3C1A");
|
||||
var r3 = CreateCell("Auto height\n(fits content)", "#FFECB3", "#3C3A1A");
|
||||
var r4 = CreateCell("40px height", "#F8BBD9", "#3C1A3C");
|
||||
|
||||
Grid.SetRow(r1, 0);
|
||||
Grid.SetRow(r2, 1);
|
||||
Grid.SetRow(r3, 2);
|
||||
Grid.SetRow(r4, 3);
|
||||
|
||||
grid.Children.Add(r1);
|
||||
grid.Children.Add(r2);
|
||||
grid.Children.Add(r3);
|
||||
grid.Children.Add(r4);
|
||||
|
||||
return CreateDemoContainer(grid, "Different row heights: 30px, 50px, Auto, 40px");
|
||||
}
|
||||
|
||||
private View CreateStarSizingDemo()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
|
||||
new ColumnDefinition { Width = new GridLength(2, GridUnitType.Star) },
|
||||
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
|
||||
}
|
||||
};
|
||||
grid.SetAppThemeColor(Grid.BackgroundColorProperty,
|
||||
Color.FromArgb("#F5F5F5"),
|
||||
Color.FromArgb("#2C2C2C"));
|
||||
|
||||
var s1 = CreateCell("1*", "#BBDEFB", "#1A3A5C");
|
||||
var s2 = CreateCell("2* (double)", "#C8E6C9", "#1A3C1A");
|
||||
var s3 = CreateCell("1*", "#FFECB3", "#3C3A1A");
|
||||
|
||||
Grid.SetColumn(s1, 0);
|
||||
Grid.SetColumn(s2, 1);
|
||||
Grid.SetColumn(s3, 2);
|
||||
|
||||
grid.Children.Add(s1);
|
||||
grid.Children.Add(s2);
|
||||
grid.Children.Add(s3);
|
||||
|
||||
return CreateDemoContainer(grid, "Star proportions: 1* | 2* | 1* = 25% | 50% | 25%");
|
||||
}
|
||||
|
||||
private View CreateSpacingDemo()
|
||||
{
|
||||
var stack = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// No spacing
|
||||
var noSpacing = CreateSpacedGrid(0, 0);
|
||||
var noLabel = new Label { Text = "No spacing (RowSpacing=0, ColumnSpacing=0)", FontSize = 12 };
|
||||
noLabel.SetAppThemeColor(Label.TextColorProperty,
|
||||
Color.FromArgb("#757575"),
|
||||
Color.FromArgb("#B0B0B0"));
|
||||
stack.Children.Add(noLabel);
|
||||
stack.Children.Add(noSpacing);
|
||||
|
||||
// With spacing
|
||||
var withSpacing = CreateSpacedGrid(10, 10);
|
||||
var withLabel = new Label { Text = "With spacing (RowSpacing=10, ColumnSpacing=10)", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) };
|
||||
withLabel.SetAppThemeColor(Label.TextColorProperty,
|
||||
Color.FromArgb("#757575"),
|
||||
Color.FromArgb("#B0B0B0"));
|
||||
stack.Children.Add(withLabel);
|
||||
stack.Children.Add(withSpacing);
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
private Grid CreateSpacedGrid(int rowSpacing, int columnSpacing)
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
RowSpacing = rowSpacing,
|
||||
ColumnSpacing = columnSpacing,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
|
||||
var c1 = CreateCell("0,0", "#BBDEFB", "#1A3A5C");
|
||||
var c2 = CreateCell("0,1", "#C8E6C9", "#1A3C1A");
|
||||
var c3 = CreateCell("1,0", "#FFECB3", "#3C3A1A");
|
||||
var c4 = CreateCell("1,1", "#F8BBD9", "#3C1A3C");
|
||||
|
||||
Grid.SetRow(c1, 0); Grid.SetColumn(c1, 0);
|
||||
Grid.SetRow(c2, 0); Grid.SetColumn(c2, 1);
|
||||
Grid.SetRow(c3, 1); Grid.SetColumn(c3, 0);
|
||||
Grid.SetRow(c4, 1); Grid.SetColumn(c4, 1);
|
||||
|
||||
grid.Children.Add(c1);
|
||||
grid.Children.Add(c2);
|
||||
grid.Children.Add(c3);
|
||||
grid.Children.Add(c4);
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
private View CreateSpanDemo()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
RowSpacing = 5,
|
||||
ColumnSpacing = 5,
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Star }
|
||||
}
|
||||
};
|
||||
|
||||
// Spanning header
|
||||
var header = CreateCell("ColumnSpan=3 (Header)", "#1976D2", "#0D47A1", Colors.White);
|
||||
Grid.SetRow(header, 0);
|
||||
Grid.SetColumn(header, 0);
|
||||
Grid.SetColumnSpan(header, 3);
|
||||
|
||||
// Left sidebar spanning 2 rows
|
||||
var sidebar = CreateCell("RowSpan=2\n(Sidebar)", "#388E3C", "#1B5E20", Colors.White);
|
||||
Grid.SetRow(sidebar, 1);
|
||||
Grid.SetColumn(sidebar, 0);
|
||||
Grid.SetRowSpan(sidebar, 2);
|
||||
|
||||
// Content cells
|
||||
var content1 = CreateCell("Content 1", "#E3F2FD", "#1A3A5C");
|
||||
Grid.SetRow(content1, 1); Grid.SetColumn(content1, 1);
|
||||
|
||||
var content2 = CreateCell("Content 2", "#E8F5E9", "#1A3C1A");
|
||||
Grid.SetRow(content2, 1); Grid.SetColumn(content2, 2);
|
||||
|
||||
var content3 = CreateCell("Content 3", "#FFF3E0", "#3C2A1A");
|
||||
Grid.SetRow(content3, 2); Grid.SetColumn(content3, 1);
|
||||
|
||||
var content4 = CreateCell("Content 4", "#FCE4EC", "#3C1A2A");
|
||||
Grid.SetRow(content4, 2); Grid.SetColumn(content4, 2);
|
||||
|
||||
grid.Children.Add(header);
|
||||
grid.Children.Add(sidebar);
|
||||
grid.Children.Add(content1);
|
||||
grid.Children.Add(content2);
|
||||
grid.Children.Add(content3);
|
||||
grid.Children.Add(content4);
|
||||
|
||||
return CreateDemoContainer(grid, "Header spans 3 columns, Sidebar spans 2 rows");
|
||||
}
|
||||
|
||||
private View CreateMixedSizingDemo()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
ColumnSpacing = 5,
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(60) },
|
||||
new ColumnDefinition { Width = GridLength.Star },
|
||||
new ColumnDefinition { Width = GridLength.Auto },
|
||||
new ColumnDefinition { Width = new GridLength(60) }
|
||||
}
|
||||
};
|
||||
grid.SetAppThemeColor(Grid.BackgroundColorProperty,
|
||||
Color.FromArgb("#F5F5F5"),
|
||||
Color.FromArgb("#2C2C2C"));
|
||||
|
||||
var c1 = CreateCell("60px", "#BBDEFB", "#1A3A5C");
|
||||
var c2 = CreateCell("Star (fills remaining)", "#C8E6C9", "#1A3C1A");
|
||||
var c3 = CreateCell("Auto", "#FFECB3", "#3C3A1A");
|
||||
var c4 = CreateCell("60px", "#F8BBD9", "#3C1A3C");
|
||||
|
||||
Grid.SetColumn(c1, 0);
|
||||
Grid.SetColumn(c2, 1);
|
||||
Grid.SetColumn(c3, 2);
|
||||
Grid.SetColumn(c4, 3);
|
||||
|
||||
grid.Children.Add(c1);
|
||||
grid.Children.Add(c2);
|
||||
grid.Children.Add(c3);
|
||||
grid.Children.Add(c4);
|
||||
|
||||
return CreateDemoContainer(grid, "Mixed: 60px | Star | Auto | 60px");
|
||||
}
|
||||
|
||||
private Border CreateCell(string text, string lightBgColor, string darkBgColor, Color? textColor = null)
|
||||
{
|
||||
var label = new Label
|
||||
{
|
||||
Text = text,
|
||||
FontSize = 12,
|
||||
HorizontalTextAlignment = TextAlignment.Center,
|
||||
VerticalTextAlignment = TextAlignment.Center
|
||||
};
|
||||
|
||||
if (textColor != null)
|
||||
{
|
||||
label.TextColor = textColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
label.SetAppThemeColor(Label.TextColorProperty,
|
||||
Colors.Black,
|
||||
Colors.White);
|
||||
}
|
||||
|
||||
var border = new Border
|
||||
{
|
||||
Padding = new Thickness(10, 8),
|
||||
StrokeThickness = 0,
|
||||
Content = label
|
||||
};
|
||||
|
||||
border.SetAppThemeColor(Border.BackgroundColorProperty,
|
||||
Color.FromArgb(lightBgColor),
|
||||
Color.FromArgb(darkBgColor));
|
||||
|
||||
return border;
|
||||
}
|
||||
|
||||
private View CreateDemoContainer(View content, string description)
|
||||
{
|
||||
var descLabel = new Label { Text = description, FontSize = 12 };
|
||||
descLabel.SetAppThemeColor(Label.TextColorProperty,
|
||||
Color.FromArgb("#757575"),
|
||||
Color.FromArgb("#B0B0B0"));
|
||||
|
||||
return new VerticalStackLayout
|
||||
{
|
||||
Spacing = 5,
|
||||
Children = { descLabel, content }
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
// HomePage - Welcome page for the demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public class HomePage : ContentPage
|
||||
{
|
||||
public HomePage()
|
||||
{
|
||||
Title = "Home";
|
||||
|
||||
Content = new ScrollView
|
||||
{
|
||||
Orientation = ScrollOrientation.Both, // Enable horizontal scrolling when window is too narrow
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = new Thickness(30),
|
||||
Spacing = 20,
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = "OpenMaui Linux",
|
||||
FontSize = 32,
|
||||
FontAttributes = FontAttributes.Bold,
|
||||
HorizontalOptions = LayoutOptions.Center,
|
||||
TextColor = Color.FromArgb("#2196F3")
|
||||
},
|
||||
|
||||
new Label
|
||||
{
|
||||
Text = "Controls Demo",
|
||||
FontSize = 20,
|
||||
HorizontalOptions = LayoutOptions.Center,
|
||||
TextColor = Colors.Gray
|
||||
},
|
||||
|
||||
new BoxView
|
||||
{
|
||||
HeightRequest = 2,
|
||||
Color = Color.FromArgb("#E0E0E0"),
|
||||
Margin = new Thickness(0, 10)
|
||||
},
|
||||
|
||||
new Label
|
||||
{
|
||||
Text = "Welcome to the comprehensive controls demonstration for OpenMaui Linux. " +
|
||||
"This app showcases all the major UI controls available in the framework.",
|
||||
FontSize = 14,
|
||||
LineBreakMode = LineBreakMode.WordWrap,
|
||||
HorizontalTextAlignment = TextAlignment.Center
|
||||
},
|
||||
|
||||
CreateFeatureSection(),
|
||||
|
||||
new Label
|
||||
{
|
||||
Text = "Use the flyout menu (swipe from left or tap the hamburger icon) to navigate between different control demos.",
|
||||
FontSize = 12,
|
||||
TextColor = Colors.Gray,
|
||||
LineBreakMode = LineBreakMode.WordWrap,
|
||||
HorizontalTextAlignment = TextAlignment.Center,
|
||||
Margin = new Thickness(0, 20, 0, 0)
|
||||
},
|
||||
|
||||
CreateQuickLinksSection(),
|
||||
|
||||
CreateNavigationDemoSection()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateFeatureSection()
|
||||
{
|
||||
var grid = new Grid
|
||||
{
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
|
||||
new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
|
||||
},
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto },
|
||||
new RowDefinition { Height = GridLength.Auto }
|
||||
},
|
||||
ColumnSpacing = 15,
|
||||
RowSpacing = 15,
|
||||
Margin = new Thickness(0, 20)
|
||||
};
|
||||
|
||||
var features = new[]
|
||||
{
|
||||
("Buttons", "Various button styles and events"),
|
||||
("Text Input", "Entry, Editor, SearchBar"),
|
||||
("Selection", "CheckBox, Switch, Slider"),
|
||||
("Pickers", "Picker, DatePicker, TimePicker"),
|
||||
("Lists", "CollectionView with selection"),
|
||||
("Progress", "ProgressBar, ActivityIndicator")
|
||||
};
|
||||
|
||||
for (int i = 0; i < features.Length; i++)
|
||||
{
|
||||
var (title, desc) = features[i];
|
||||
var card = CreateFeatureCard(title, desc);
|
||||
Grid.SetRow(card, i / 2);
|
||||
Grid.SetColumn(card, i % 2);
|
||||
grid.Children.Add(card);
|
||||
}
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
private Frame CreateFeatureCard(string title, string description)
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
CornerRadius = 8,
|
||||
Padding = new Thickness(15),
|
||||
BackgroundColor = Colors.White,
|
||||
HasShadow = true,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 5,
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = title,
|
||||
FontSize = 14,
|
||||
FontAttributes = FontAttributes.Bold,
|
||||
TextColor = Color.FromArgb("#2196F3")
|
||||
},
|
||||
new Label
|
||||
{
|
||||
Text = description,
|
||||
FontSize = 11,
|
||||
TextColor = Colors.Gray,
|
||||
LineBreakMode = LineBreakMode.WordWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateQuickLinksSection()
|
||||
{
|
||||
var layout = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
Margin = new Thickness(0, 20, 0, 0)
|
||||
};
|
||||
|
||||
layout.Children.Add(new Label
|
||||
{
|
||||
Text = "Quick Actions",
|
||||
FontSize = 16,
|
||||
FontAttributes = FontAttributes.Bold,
|
||||
HorizontalOptions = LayoutOptions.Center
|
||||
});
|
||||
|
||||
var buttonRow = new HorizontalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
HorizontalOptions = LayoutOptions.Center
|
||||
};
|
||||
|
||||
var buttonsBtn = new Button
|
||||
{
|
||||
Text = "Try Buttons",
|
||||
BackgroundColor = Color.FromArgb("#2196F3"),
|
||||
TextColor = Colors.White
|
||||
};
|
||||
buttonsBtn.Clicked += (s, e) => LinuxViewRenderer.NavigateToRoute("Buttons");
|
||||
|
||||
var listsBtn = new Button
|
||||
{
|
||||
Text = "Try Lists",
|
||||
BackgroundColor = Color.FromArgb("#4CAF50"),
|
||||
TextColor = Colors.White
|
||||
};
|
||||
listsBtn.Clicked += (s, e) => LinuxViewRenderer.NavigateToRoute("Lists");
|
||||
|
||||
buttonRow.Children.Add(buttonsBtn);
|
||||
buttonRow.Children.Add(listsBtn);
|
||||
layout.Children.Add(buttonRow);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateNavigationDemoSection()
|
||||
{
|
||||
var frame = new Frame
|
||||
{
|
||||
CornerRadius = 8,
|
||||
Padding = new Thickness(20),
|
||||
BackgroundColor = Color.FromArgb("#F3E5F5"),
|
||||
Margin = new Thickness(0, 20, 0, 0),
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 15,
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = "Navigation Stack Demo",
|
||||
FontSize = 18,
|
||||
FontAttributes = FontAttributes.Bold,
|
||||
TextColor = Color.FromArgb("#9C27B0"),
|
||||
HorizontalOptions = LayoutOptions.Center
|
||||
},
|
||||
|
||||
new Label
|
||||
{
|
||||
Text = "Demonstrate push/pop navigation using Shell.GoToAsync()",
|
||||
FontSize = 12,
|
||||
TextColor = Colors.Gray,
|
||||
HorizontalTextAlignment = TextAlignment.Center
|
||||
},
|
||||
|
||||
CreatePushButton("Push Detail Page", "detail"),
|
||||
|
||||
new Label
|
||||
{
|
||||
Text = "Click the button to push a new page onto the navigation stack. " +
|
||||
"Use the back button or 'Go Back' to pop it off.",
|
||||
FontSize = 11,
|
||||
TextColor = Colors.Gray,
|
||||
HorizontalTextAlignment = TextAlignment.Center,
|
||||
LineBreakMode = LineBreakMode.WordWrap
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
private Button CreatePushButton(string text, string route)
|
||||
{
|
||||
var btn = new Button
|
||||
{
|
||||
Text = text,
|
||||
BackgroundColor = Color.FromArgb("#9C27B0"),
|
||||
TextColor = Colors.White,
|
||||
HorizontalOptions = LayoutOptions.Center,
|
||||
Padding = new Thickness(30, 10)
|
||||
};
|
||||
|
||||
btn.Clicked += (s, e) =>
|
||||
{
|
||||
Console.WriteLine($"[HomePage] Push button clicked, navigating to {route}");
|
||||
// Use LinuxViewRenderer.PushPage for Skia-based navigation
|
||||
var success = LinuxViewRenderer.PushPage(new DetailPage());
|
||||
Console.WriteLine($"[HomePage] PushPage result: {success}");
|
||||
};
|
||||
|
||||
return btn;
|
||||
}
|
||||
}
|
||||
105
ShellDemo/Pages/HomePage.xaml
Normal file
105
ShellDemo/Pages/HomePage.xaml
Normal file
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.HomePage"
|
||||
Title="Home"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<ScrollView Orientation="Both">
|
||||
<VerticalStackLayout Padding="30" Spacing="20">
|
||||
|
||||
<!-- Header -->
|
||||
<Label Text="OpenMaui Linux"
|
||||
FontSize="32"
|
||||
FontAttributes="Bold"
|
||||
HorizontalOptions="Center"
|
||||
TextColor="{StaticResource PrimaryColor}" />
|
||||
|
||||
<Label Text="Controls Demo"
|
||||
FontSize="20"
|
||||
HorizontalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
|
||||
<BoxView Style="{StaticResource ThemedDivider}" Margin="0,10" />
|
||||
|
||||
<Label Text="Welcome to the comprehensive controls demonstration for OpenMaui Linux. This app showcases all the major UI controls available in the framework."
|
||||
FontSize="14"
|
||||
LineBreakMode="WordWrap"
|
||||
HorizontalTextAlignment="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Feature Grid -->
|
||||
<Grid x:Name="FeatureGrid"
|
||||
ColumnDefinitions="*,*"
|
||||
RowDefinitions="Auto,Auto,Auto"
|
||||
ColumnSpacing="15"
|
||||
RowSpacing="15"
|
||||
Margin="0,20" />
|
||||
|
||||
<Label Text="Use the flyout menu (swipe from left or tap the hamburger icon) to navigate between different control demos."
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
LineBreakMode="WordWrap"
|
||||
HorizontalTextAlignment="Center"
|
||||
Margin="0,20,0,0" />
|
||||
|
||||
<!-- Quick Actions Section -->
|
||||
<VerticalStackLayout Spacing="10" Margin="0,20,0,0">
|
||||
<Label Text="Quick Actions"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
HorizontalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<HorizontalStackLayout Spacing="10" HorizontalOptions="Center">
|
||||
<Button x:Name="TryButtonsBtn"
|
||||
Text="Try Buttons"
|
||||
Style="{StaticResource PrimaryButton}"
|
||||
Clicked="OnTryButtonsClicked" />
|
||||
<Button x:Name="TryListsBtn"
|
||||
Text="Try Lists"
|
||||
Style="{StaticResource SuccessButton}"
|
||||
Clicked="OnTryListsClicked" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
|
||||
<!-- Navigation Demo Section -->
|
||||
<Border BackgroundColor="{AppThemeBinding Light=#F3E5F5, Dark=#2D1F3D}"
|
||||
StrokeThickness="0"
|
||||
Padding="20"
|
||||
Margin="0,20,0,0">
|
||||
<Border.StrokeShape>
|
||||
<RoundRectangle CornerRadius="8" />
|
||||
</Border.StrokeShape>
|
||||
|
||||
<VerticalStackLayout Spacing="15">
|
||||
<Label Text="Navigation Stack Demo"
|
||||
FontSize="18"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{StaticResource PurpleColor}"
|
||||
HorizontalOptions="Center" />
|
||||
|
||||
<Label Text="Demonstrate push/pop navigation using Shell.GoToAsync()"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
HorizontalTextAlignment="Center" />
|
||||
|
||||
<Button x:Name="PushDetailBtn"
|
||||
Text="Push Detail Page"
|
||||
BackgroundColor="{StaticResource PurpleColor}"
|
||||
TextColor="White"
|
||||
HorizontalOptions="Center"
|
||||
Padding="30,10"
|
||||
Clicked="OnPushDetailClicked" />
|
||||
|
||||
<Label Text="Click the button to push a new page onto the navigation stack. Use the back button or 'Go Back' to pop it off."
|
||||
FontSize="11"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
HorizontalTextAlignment="Center"
|
||||
LineBreakMode="WordWrap" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
||||
121
ShellDemo/Pages/HomePage.xaml.cs
Normal file
121
ShellDemo/Pages/HomePage.xaml.cs
Normal file
@@ -0,0 +1,121 @@
|
||||
// HomePage - Welcome page for the demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
using Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class HomePage : ContentPage
|
||||
{
|
||||
public HomePage()
|
||||
{
|
||||
InitializeComponent();
|
||||
CreateFeatureCards();
|
||||
}
|
||||
|
||||
private void CreateFeatureCards()
|
||||
{
|
||||
var features = new[]
|
||||
{
|
||||
("Buttons", "Various button styles and events"),
|
||||
("Text Input", "Entry, Editor, SearchBar"),
|
||||
("Selection", "CheckBox, Switch, Slider"),
|
||||
("Pickers", "Picker, DatePicker, TimePicker"),
|
||||
("Lists", "CollectionView with selection"),
|
||||
("Progress", "ProgressBar, ActivityIndicator")
|
||||
};
|
||||
|
||||
for (int i = 0; i < features.Length; i++)
|
||||
{
|
||||
var (title, desc) = features[i];
|
||||
var card = CreateFeatureCard(title, desc);
|
||||
Grid.SetRow(card, i / 2);
|
||||
Grid.SetColumn(card, i % 2);
|
||||
FeatureGrid.Children.Add(card);
|
||||
}
|
||||
}
|
||||
|
||||
private Border CreateFeatureCard(string title, string description)
|
||||
{
|
||||
// Use AppThemeBinding for card colors
|
||||
var cardBackground = new AppThemeBindingExtension
|
||||
{
|
||||
Light = Application.Current?.Resources["CardBackgroundLight"] as Color ?? Colors.White,
|
||||
Dark = Application.Current?.Resources["CardBackgroundDark"] as Color ?? Color.FromArgb("#1E1E1E")
|
||||
};
|
||||
|
||||
var textPrimary = new AppThemeBindingExtension
|
||||
{
|
||||
Light = Application.Current?.Resources["TextPrimaryLight"] as Color ?? Colors.Black,
|
||||
Dark = Application.Current?.Resources["TextPrimaryDark"] as Color ?? Colors.White
|
||||
};
|
||||
|
||||
var textSecondary = new AppThemeBindingExtension
|
||||
{
|
||||
Light = Application.Current?.Resources["TextSecondaryLight"] as Color ?? Colors.Gray,
|
||||
Dark = Application.Current?.Resources["TextSecondaryDark"] as Color ?? Color.FromArgb("#B0B0B0")
|
||||
};
|
||||
|
||||
var titleLabel = new Label
|
||||
{
|
||||
Text = title,
|
||||
FontSize = 14,
|
||||
FontAttributes = FontAttributes.Bold,
|
||||
TextColor = Color.FromArgb("#2196F3")
|
||||
};
|
||||
|
||||
var descLabel = new Label
|
||||
{
|
||||
Text = description,
|
||||
FontSize = 11,
|
||||
LineBreakMode = LineBreakMode.WordWrap
|
||||
};
|
||||
descLabel.SetBinding(Label.TextColorProperty, new Binding { Source = textSecondary, Path = "." });
|
||||
descLabel.SetAppThemeColor(Label.TextColorProperty,
|
||||
Application.Current?.Resources["TextSecondaryLight"] as Color ?? Colors.Gray,
|
||||
Application.Current?.Resources["TextSecondaryDark"] as Color ?? Color.FromArgb("#B0B0B0"));
|
||||
|
||||
var border = new Border
|
||||
{
|
||||
Padding = new Thickness(15),
|
||||
StrokeThickness = 0,
|
||||
StrokeShape = new RoundRectangle { CornerRadius = 8 },
|
||||
Shadow = new Shadow
|
||||
{
|
||||
Brush = new SolidColorBrush(Colors.Black),
|
||||
Opacity = 0.1f,
|
||||
Radius = 4,
|
||||
Offset = new Point(0, 2)
|
||||
},
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 5,
|
||||
Children = { titleLabel, descLabel }
|
||||
}
|
||||
};
|
||||
|
||||
border.SetAppThemeColor(Border.BackgroundColorProperty,
|
||||
Application.Current?.Resources["CardBackgroundLight"] as Color ?? Colors.White,
|
||||
Application.Current?.Resources["CardBackgroundDark"] as Color ?? Color.FromArgb("#1E1E1E"));
|
||||
|
||||
return border;
|
||||
}
|
||||
|
||||
private void OnTryButtonsClicked(object? sender, EventArgs e)
|
||||
{
|
||||
LinuxViewRenderer.NavigateToRoute("Buttons");
|
||||
}
|
||||
|
||||
private void OnTryListsClicked(object? sender, EventArgs e)
|
||||
{
|
||||
LinuxViewRenderer.NavigateToRoute("Lists");
|
||||
}
|
||||
|
||||
private void OnPushDetailClicked(object? sender, EventArgs e)
|
||||
{
|
||||
Console.WriteLine("[HomePage] Push button clicked, navigating to detail");
|
||||
var success = LinuxViewRenderer.PushPage(new DetailPage());
|
||||
Console.WriteLine($"[HomePage] PushPage result: {success}");
|
||||
}
|
||||
}
|
||||
@@ -1,249 +0,0 @@
|
||||
// ListsPage - CollectionView and ListView Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public class ListsPage : ContentPage
|
||||
{
|
||||
private readonly Label _eventLog;
|
||||
private int _eventCount = 0;
|
||||
|
||||
public ListsPage()
|
||||
{
|
||||
Title = "Lists";
|
||||
|
||||
_eventLog = new Label
|
||||
{
|
||||
Text = "Events will appear here...",
|
||||
FontSize = 11,
|
||||
TextColor = Colors.Gray,
|
||||
LineBreakMode = LineBreakMode.WordWrap
|
||||
};
|
||||
|
||||
Content = new Grid
|
||||
{
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
|
||||
new RowDefinition { Height = new GridLength(120) }
|
||||
},
|
||||
Children =
|
||||
{
|
||||
CreateMainContent(),
|
||||
CreateEventLogPanel()
|
||||
}
|
||||
};
|
||||
|
||||
Grid.SetRow((View)((Grid)Content).Children[0], 0);
|
||||
Grid.SetRow((View)((Grid)Content).Children[1], 1);
|
||||
}
|
||||
|
||||
private View CreateMainContent()
|
||||
{
|
||||
return new ScrollView
|
||||
{
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = new Thickness(20),
|
||||
Spacing = 20,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "List Controls", FontSize = 24, FontAttributes = FontAttributes.Bold },
|
||||
|
||||
CreateSection("CollectionView - Fruits", CreateFruitsCollectionView()),
|
||||
CreateSection("CollectionView - Colors", CreateColorsCollectionView()),
|
||||
CreateSection("CollectionView - Contacts", CreateContactsCollectionView())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateFruitsCollectionView()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 10 };
|
||||
|
||||
var fruits = new List<string>
|
||||
{
|
||||
"Apple", "Banana", "Cherry", "Date", "Elderberry",
|
||||
"Fig", "Grape", "Honeydew", "Kiwi", "Lemon",
|
||||
"Mango", "Nectarine", "Orange", "Papaya", "Quince"
|
||||
};
|
||||
|
||||
var selectedLabel = new Label { Text = "Tap a fruit to select", TextColor = Colors.Gray };
|
||||
|
||||
var collectionView = new CollectionView
|
||||
{
|
||||
ItemsSource = fruits,
|
||||
HeightRequest = 200,
|
||||
SelectionMode = SelectionMode.Single,
|
||||
BackgroundColor = Color.FromArgb("#FAFAFA")
|
||||
};
|
||||
|
||||
collectionView.SelectionChanged += (s, e) =>
|
||||
{
|
||||
if (e.CurrentSelection.Count > 0)
|
||||
{
|
||||
var item = e.CurrentSelection[0]?.ToString();
|
||||
selectedLabel.Text = $"Selected: {item}";
|
||||
LogEvent($"Fruit selected: {item}");
|
||||
}
|
||||
};
|
||||
|
||||
layout.Children.Add(collectionView);
|
||||
layout.Children.Add(selectedLabel);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateColorsCollectionView()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 10 };
|
||||
|
||||
var colors = new List<ColorItem>
|
||||
{
|
||||
new("Red", "#F44336"),
|
||||
new("Pink", "#E91E63"),
|
||||
new("Purple", "#9C27B0"),
|
||||
new("Deep Purple", "#673AB7"),
|
||||
new("Indigo", "#3F51B5"),
|
||||
new("Blue", "#2196F3"),
|
||||
new("Cyan", "#00BCD4"),
|
||||
new("Teal", "#009688"),
|
||||
new("Green", "#4CAF50"),
|
||||
new("Light Green", "#8BC34A"),
|
||||
new("Lime", "#CDDC39"),
|
||||
new("Yellow", "#FFEB3B"),
|
||||
new("Amber", "#FFC107"),
|
||||
new("Orange", "#FF9800"),
|
||||
new("Deep Orange", "#FF5722")
|
||||
};
|
||||
|
||||
var collectionView = new CollectionView
|
||||
{
|
||||
ItemsSource = colors,
|
||||
HeightRequest = 180,
|
||||
SelectionMode = SelectionMode.Single,
|
||||
BackgroundColor = Colors.White
|
||||
};
|
||||
|
||||
collectionView.SelectionChanged += (s, e) =>
|
||||
{
|
||||
if (e.CurrentSelection.Count > 0 && e.CurrentSelection[0] is ColorItem item)
|
||||
{
|
||||
LogEvent($"Color selected: {item.Name} ({item.Hex})");
|
||||
}
|
||||
};
|
||||
|
||||
layout.Children.Add(collectionView);
|
||||
layout.Children.Add(new Label { Text = "Scroll to see all colors", FontSize = 11, TextColor = Colors.Gray });
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateContactsCollectionView()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 10 };
|
||||
|
||||
var contacts = new List<ContactItem>
|
||||
{
|
||||
new("Alice Johnson", "alice@example.com", "Engineering"),
|
||||
new("Bob Smith", "bob@example.com", "Marketing"),
|
||||
new("Carol Williams", "carol@example.com", "Design"),
|
||||
new("David Brown", "david@example.com", "Sales"),
|
||||
new("Eva Martinez", "eva@example.com", "Engineering"),
|
||||
new("Frank Lee", "frank@example.com", "Support"),
|
||||
new("Grace Kim", "grace@example.com", "HR"),
|
||||
new("Henry Wilson", "henry@example.com", "Finance")
|
||||
};
|
||||
|
||||
var collectionView = new CollectionView
|
||||
{
|
||||
ItemsSource = contacts,
|
||||
HeightRequest = 200,
|
||||
SelectionMode = SelectionMode.Single,
|
||||
BackgroundColor = Colors.White
|
||||
};
|
||||
|
||||
collectionView.SelectionChanged += (s, e) =>
|
||||
{
|
||||
if (e.CurrentSelection.Count > 0 && e.CurrentSelection[0] is ContactItem contact)
|
||||
{
|
||||
LogEvent($"Contact: {contact.Name} - {contact.Department}");
|
||||
}
|
||||
};
|
||||
|
||||
layout.Children.Add(collectionView);
|
||||
|
||||
// Action buttons
|
||||
var buttonRow = new HorizontalStackLayout { Spacing = 10 };
|
||||
var addBtn = new Button { Text = "Add Contact", BackgroundColor = Colors.Green, TextColor = Colors.White };
|
||||
addBtn.Clicked += (s, e) => LogEvent("Add contact clicked");
|
||||
var deleteBtn = new Button { Text = "Delete Selected", BackgroundColor = Colors.Red, TextColor = Colors.White };
|
||||
deleteBtn.Clicked += (s, e) => LogEvent("Delete contact clicked");
|
||||
buttonRow.Children.Add(addBtn);
|
||||
buttonRow.Children.Add(deleteBtn);
|
||||
layout.Children.Add(buttonRow);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private Frame CreateSection(string title, View content)
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
CornerRadius = 8,
|
||||
Padding = new Thickness(15),
|
||||
BackgroundColor = Colors.White,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = title, FontSize = 16, FontAttributes = FontAttributes.Bold },
|
||||
content
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateEventLogPanel()
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5"),
|
||||
Padding = new Thickness(10),
|
||||
CornerRadius = 0,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "Event Log:", FontSize = 12, FontAttributes = FontAttributes.Bold },
|
||||
new ScrollView
|
||||
{
|
||||
HeightRequest = 80,
|
||||
Content = _eventLog
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void LogEvent(string message)
|
||||
{
|
||||
_eventCount++;
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
_eventLog.Text = $"[{timestamp}] {_eventCount}. {message}\n{_eventLog.Text}";
|
||||
}
|
||||
}
|
||||
|
||||
public record ColorItem(string Name, string Hex)
|
||||
{
|
||||
public override string ToString() => Name;
|
||||
}
|
||||
|
||||
public record ContactItem(string Name, string Email, string Department)
|
||||
{
|
||||
public override string ToString() => $"{Name} ({Department})";
|
||||
}
|
||||
133
ShellDemo/Pages/ListsPage.xaml
Normal file
133
ShellDemo/Pages/ListsPage.xaml
Normal file
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.ListsPage"
|
||||
Title="Lists"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<Grid RowDefinitions="*,120">
|
||||
|
||||
<!-- Main Content -->
|
||||
<ScrollView Grid.Row="0">
|
||||
<VerticalStackLayout Padding="20" Spacing="20">
|
||||
|
||||
<Label Text="List Controls"
|
||||
FontSize="24"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Fruits CollectionView -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="CollectionView - Fruits"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<CollectionView x:Name="FruitsCollectionView"
|
||||
HeightRequest="200"
|
||||
SelectionMode="Single"
|
||||
BackgroundColor="{AppThemeBinding Light=#FAFAFA, Dark=#2C2C2C}"
|
||||
SelectionChanged="OnFruitsSelectionChanged">
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Label Text="{Binding}"
|
||||
Padding="10"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</DataTemplate>
|
||||
</CollectionView.ItemTemplate>
|
||||
</CollectionView>
|
||||
|
||||
<Label x:Name="FruitsSelectedLabel"
|
||||
Text="Tap a fruit to select"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Colors CollectionView -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="CollectionView - Colors"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<CollectionView x:Name="ColorsCollectionView"
|
||||
HeightRequest="180"
|
||||
SelectionMode="Single"
|
||||
BackgroundColor="{AppThemeBinding Light=White, Dark=#1E1E1E}"
|
||||
SelectionChanged="OnColorsSelectionChanged">
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Label Text="{Binding}"
|
||||
Padding="10"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</DataTemplate>
|
||||
</CollectionView.ItemTemplate>
|
||||
</CollectionView>
|
||||
|
||||
<Label Text="Scroll to see all colors"
|
||||
FontSize="11"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Contacts CollectionView -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="10">
|
||||
<Label Text="CollectionView - Contacts"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<CollectionView x:Name="ContactsCollectionView"
|
||||
HeightRequest="200"
|
||||
SelectionMode="Single"
|
||||
BackgroundColor="{AppThemeBinding Light=White, Dark=#1E1E1E}"
|
||||
SelectionChanged="OnContactsSelectionChanged">
|
||||
<CollectionView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Label Text="{Binding}"
|
||||
Padding="10"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</DataTemplate>
|
||||
</CollectionView.ItemTemplate>
|
||||
</CollectionView>
|
||||
|
||||
<!-- Action buttons -->
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Button Text="Add Contact"
|
||||
Style="{StaticResource SuccessButton}"
|
||||
Clicked="OnAddContactClicked" />
|
||||
<Button Text="Delete Selected"
|
||||
Style="{StaticResource DangerButton}"
|
||||
Clicked="OnDeleteContactClicked" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- Event Log Panel -->
|
||||
<Border Grid.Row="1"
|
||||
BackgroundColor="{AppThemeBinding Light=#F5F5F5, Dark=#2C2C2C}"
|
||||
StrokeThickness="0"
|
||||
Padding="10">
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Event Log:"
|
||||
FontSize="12"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<ScrollView HeightRequest="80">
|
||||
<Label x:Name="EventLogLabel"
|
||||
Text="Events will appear here..."
|
||||
FontSize="11"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
LineBreakMode="WordWrap" />
|
||||
</ScrollView>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
104
ShellDemo/Pages/ListsPage.xaml.cs
Normal file
104
ShellDemo/Pages/ListsPage.xaml.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
// ListsPage - CollectionView and ListView Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class ListsPage : ContentPage
|
||||
{
|
||||
private int _eventCount = 0;
|
||||
private ObservableCollection<string> _contacts;
|
||||
|
||||
public ListsPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Set up fruits
|
||||
var fruits = new List<string>
|
||||
{
|
||||
"Apple", "Banana", "Cherry", "Date", "Elderberry",
|
||||
"Fig", "Grape", "Honeydew", "Kiwi", "Lemon",
|
||||
"Mango", "Nectarine", "Orange", "Papaya", "Quince"
|
||||
};
|
||||
FruitsCollectionView.ItemsSource = fruits;
|
||||
|
||||
// Set up colors
|
||||
var colors = new List<string>
|
||||
{
|
||||
"Red", "Pink", "Purple", "Deep Purple", "Indigo",
|
||||
"Blue", "Cyan", "Teal", "Green", "Light Green",
|
||||
"Lime", "Yellow", "Amber", "Orange", "Deep Orange"
|
||||
};
|
||||
ColorsCollectionView.ItemsSource = colors;
|
||||
|
||||
// Set up contacts
|
||||
_contacts = new ObservableCollection<string>
|
||||
{
|
||||
"Alice Johnson (Engineering)",
|
||||
"Bob Smith (Marketing)",
|
||||
"Carol Williams (Design)",
|
||||
"David Brown (Sales)",
|
||||
"Eva Martinez (Engineering)",
|
||||
"Frank Lee (Support)",
|
||||
"Grace Kim (HR)",
|
||||
"Henry Wilson (Finance)"
|
||||
};
|
||||
ContactsCollectionView.ItemsSource = _contacts;
|
||||
}
|
||||
|
||||
private void OnFruitsSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.CurrentSelection.Count > 0)
|
||||
{
|
||||
var item = e.CurrentSelection[0]?.ToString();
|
||||
FruitsSelectedLabel.Text = $"Selected: {item}";
|
||||
LogEvent($"Fruit selected: {item}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnColorsSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.CurrentSelection.Count > 0)
|
||||
{
|
||||
var item = e.CurrentSelection[0]?.ToString();
|
||||
LogEvent($"Color selected: {item}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnContactsSelectionChanged(object? sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (e.CurrentSelection.Count > 0)
|
||||
{
|
||||
var contact = e.CurrentSelection[0]?.ToString();
|
||||
LogEvent($"Contact: {contact}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAddContactClicked(object? sender, EventArgs e)
|
||||
{
|
||||
var newContact = $"New Contact {_contacts.Count + 1} (New)";
|
||||
_contacts.Add(newContact);
|
||||
LogEvent($"Added: {newContact}");
|
||||
}
|
||||
|
||||
private void OnDeleteContactClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (ContactsCollectionView.SelectedItem is string selected && _contacts.Contains(selected))
|
||||
{
|
||||
_contacts.Remove(selected);
|
||||
LogEvent($"Deleted: {selected}");
|
||||
}
|
||||
else
|
||||
{
|
||||
LogEvent("No contact selected to delete");
|
||||
}
|
||||
}
|
||||
|
||||
private void LogEvent(string message)
|
||||
{
|
||||
_eventCount++;
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
EventLogLabel.Text = $"[{timestamp}] {_eventCount}. {message}\n{EventLogLabel.Text}";
|
||||
}
|
||||
}
|
||||
@@ -1,261 +0,0 @@
|
||||
// PickersPage - Picker, DatePicker, TimePicker Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public class PickersPage : ContentPage
|
||||
{
|
||||
private readonly Label _eventLog;
|
||||
private int _eventCount = 0;
|
||||
|
||||
public PickersPage()
|
||||
{
|
||||
Title = "Pickers";
|
||||
|
||||
_eventLog = new Label
|
||||
{
|
||||
Text = "Events will appear here...",
|
||||
FontSize = 11,
|
||||
TextColor = Colors.Gray,
|
||||
LineBreakMode = LineBreakMode.WordWrap
|
||||
};
|
||||
|
||||
Content = new Grid
|
||||
{
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
|
||||
new RowDefinition { Height = new GridLength(120) }
|
||||
},
|
||||
Children =
|
||||
{
|
||||
CreateMainContent(),
|
||||
CreateEventLogPanel()
|
||||
}
|
||||
};
|
||||
|
||||
Grid.SetRow((View)((Grid)Content).Children[0], 0);
|
||||
Grid.SetRow((View)((Grid)Content).Children[1], 1);
|
||||
}
|
||||
|
||||
private View CreateMainContent()
|
||||
{
|
||||
return new ScrollView
|
||||
{
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = new Thickness(20),
|
||||
Spacing = 20,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "Picker Controls", FontSize = 24, FontAttributes = FontAttributes.Bold },
|
||||
|
||||
CreateSection("Picker", CreatePickerDemo()),
|
||||
CreateSection("DatePicker", CreateDatePickerDemo()),
|
||||
CreateSection("TimePicker", CreateTimePickerDemo())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreatePickerDemo()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Basic picker
|
||||
var selectedLabel = new Label { Text = "Selected: (none)", TextColor = Colors.Gray };
|
||||
var picker1 = new Picker { Title = "Select a fruit" };
|
||||
picker1.Items.Add("Apple");
|
||||
picker1.Items.Add("Banana");
|
||||
picker1.Items.Add("Cherry");
|
||||
picker1.Items.Add("Date");
|
||||
picker1.Items.Add("Elderberry");
|
||||
picker1.Items.Add("Fig");
|
||||
picker1.Items.Add("Grape");
|
||||
picker1.SelectedIndexChanged += (s, e) =>
|
||||
{
|
||||
if (picker1.SelectedIndex >= 0)
|
||||
{
|
||||
var item = picker1.Items[picker1.SelectedIndex];
|
||||
selectedLabel.Text = $"Selected: {item}";
|
||||
LogEvent($"Fruit selected: {item}");
|
||||
}
|
||||
};
|
||||
layout.Children.Add(picker1);
|
||||
layout.Children.Add(selectedLabel);
|
||||
|
||||
// Picker with default selection
|
||||
layout.Children.Add(new Label { Text = "With Default Selection:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
var picker2 = new Picker { Title = "Select a color" };
|
||||
picker2.Items.Add("Red");
|
||||
picker2.Items.Add("Green");
|
||||
picker2.Items.Add("Blue");
|
||||
picker2.Items.Add("Yellow");
|
||||
picker2.Items.Add("Purple");
|
||||
picker2.SelectedIndex = 2; // Blue
|
||||
picker2.SelectedIndexChanged += (s, e) =>
|
||||
{
|
||||
if (picker2.SelectedIndex >= 0)
|
||||
LogEvent($"Color selected: {picker2.Items[picker2.SelectedIndex]}");
|
||||
};
|
||||
layout.Children.Add(picker2);
|
||||
|
||||
// Styled picker
|
||||
layout.Children.Add(new Label { Text = "Styled Picker:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
var picker3 = new Picker
|
||||
{
|
||||
Title = "Select size",
|
||||
TextColor = Colors.DarkBlue,
|
||||
TitleColor = Colors.Gray
|
||||
};
|
||||
picker3.Items.Add("Small");
|
||||
picker3.Items.Add("Medium");
|
||||
picker3.Items.Add("Large");
|
||||
picker3.Items.Add("Extra Large");
|
||||
picker3.SelectedIndexChanged += (s, e) =>
|
||||
{
|
||||
if (picker3.SelectedIndex >= 0)
|
||||
LogEvent($"Size selected: {picker3.Items[picker3.SelectedIndex]}");
|
||||
};
|
||||
layout.Children.Add(picker3);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateDatePickerDemo()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Basic date picker
|
||||
var dateLabel = new Label { Text = $"Selected: {DateTime.Today:d}" };
|
||||
var datePicker1 = new DatePicker { Date = DateTime.Today };
|
||||
datePicker1.DateSelected += (s, e) =>
|
||||
{
|
||||
dateLabel.Text = $"Selected: {e.NewDate:d}";
|
||||
LogEvent($"Date selected: {e.NewDate:d}");
|
||||
};
|
||||
layout.Children.Add(datePicker1);
|
||||
layout.Children.Add(dateLabel);
|
||||
|
||||
// Date picker with range
|
||||
layout.Children.Add(new Label { Text = "With Date Range (this month only):", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
var startOfMonth = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
|
||||
var endOfMonth = startOfMonth.AddMonths(1).AddDays(-1);
|
||||
var datePicker2 = new DatePicker
|
||||
{
|
||||
MinimumDate = startOfMonth,
|
||||
MaximumDate = endOfMonth,
|
||||
Date = DateTime.Today
|
||||
};
|
||||
datePicker2.DateSelected += (s, e) => LogEvent($"Date (limited): {e.NewDate:d}");
|
||||
layout.Children.Add(datePicker2);
|
||||
|
||||
// Styled date picker
|
||||
layout.Children.Add(new Label { Text = "Styled DatePicker:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
var datePicker3 = new DatePicker
|
||||
{
|
||||
Date = DateTime.Today.AddDays(7),
|
||||
TextColor = Colors.DarkGreen
|
||||
};
|
||||
datePicker3.DateSelected += (s, e) => LogEvent($"Styled date: {e.NewDate:d}");
|
||||
layout.Children.Add(datePicker3);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateTimePickerDemo()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Basic time picker
|
||||
var timeLabel = new Label { Text = $"Selected: {DateTime.Now:t}" };
|
||||
var timePicker1 = new TimePicker { Time = DateTime.Now.TimeOfDay };
|
||||
timePicker1.PropertyChanged += (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(TimePicker.Time))
|
||||
{
|
||||
var time = timePicker1.Time;
|
||||
timeLabel.Text = $"Selected: {time:hh\\:mm}";
|
||||
LogEvent($"Time selected: {time:hh\\:mm}");
|
||||
}
|
||||
};
|
||||
layout.Children.Add(timePicker1);
|
||||
layout.Children.Add(timeLabel);
|
||||
|
||||
// Styled time picker
|
||||
layout.Children.Add(new Label { Text = "Styled TimePicker:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
var timePicker2 = new TimePicker
|
||||
{
|
||||
Time = new TimeSpan(14, 30, 0),
|
||||
TextColor = Colors.DarkBlue
|
||||
};
|
||||
timePicker2.PropertyChanged += (s, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(TimePicker.Time))
|
||||
LogEvent($"Styled time: {timePicker2.Time:hh\\:mm}");
|
||||
};
|
||||
layout.Children.Add(timePicker2);
|
||||
|
||||
// Morning alarm example
|
||||
layout.Children.Add(new Label { Text = "Alarm Time:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
var alarmRow = new HorizontalStackLayout { Spacing = 10 };
|
||||
var alarmPicker = new TimePicker { Time = new TimeSpan(7, 0, 0) };
|
||||
var alarmBtn = new Button { Text = "Set Alarm", BackgroundColor = Colors.Orange, TextColor = Colors.White };
|
||||
alarmBtn.Clicked += (s, e) => LogEvent($"Alarm set for {alarmPicker.Time:hh\\:mm}");
|
||||
alarmRow.Children.Add(alarmPicker);
|
||||
alarmRow.Children.Add(alarmBtn);
|
||||
layout.Children.Add(alarmRow);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private Frame CreateSection(string title, View content)
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
CornerRadius = 8,
|
||||
Padding = new Thickness(15),
|
||||
BackgroundColor = Colors.White,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = title, FontSize = 16, FontAttributes = FontAttributes.Bold },
|
||||
content
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateEventLogPanel()
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5"),
|
||||
Padding = new Thickness(10),
|
||||
CornerRadius = 0,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "Event Log:", FontSize = 12, FontAttributes = FontAttributes.Bold },
|
||||
new ScrollView
|
||||
{
|
||||
HeightRequest = 80,
|
||||
Content = _eventLog
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void LogEvent(string message)
|
||||
{
|
||||
_eventCount++;
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
_eventLog.Text = $"[{timestamp}] {_eventCount}. {message}\n{_eventLog.Text}";
|
||||
}
|
||||
}
|
||||
185
ShellDemo/Pages/PickersPage.xaml
Normal file
185
ShellDemo/Pages/PickersPage.xaml
Normal file
@@ -0,0 +1,185 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.PickersPage"
|
||||
Title="Pickers"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<Grid RowDefinitions="*,120">
|
||||
|
||||
<!-- Main Content -->
|
||||
<ScrollView Grid.Row="0">
|
||||
<VerticalStackLayout Padding="20" Spacing="20">
|
||||
|
||||
<Label Text="Picker Controls"
|
||||
FontSize="24"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Picker Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="15">
|
||||
<Label Text="Picker"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Basic picker -->
|
||||
<Picker x:Name="FruitPicker"
|
||||
Title="Select a fruit"
|
||||
SelectedIndexChanged="OnFruitPickerChanged">
|
||||
<Picker.ItemsSource>
|
||||
<x:Array Type="{x:Type x:String}">
|
||||
<x:String>Apple</x:String>
|
||||
<x:String>Banana</x:String>
|
||||
<x:String>Cherry</x:String>
|
||||
<x:String>Date</x:String>
|
||||
<x:String>Elderberry</x:String>
|
||||
<x:String>Fig</x:String>
|
||||
<x:String>Grape</x:String>
|
||||
</x:Array>
|
||||
</Picker.ItemsSource>
|
||||
</Picker>
|
||||
<Label x:Name="FruitSelectedLabel"
|
||||
Text="Selected: (none)"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
|
||||
<!-- Picker with default selection -->
|
||||
<Label Text="With Default Selection:"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<Picker x:Name="ColorPicker"
|
||||
Title="Select a color"
|
||||
SelectedIndex="2"
|
||||
SelectedIndexChanged="OnColorPickerChanged">
|
||||
<Picker.ItemsSource>
|
||||
<x:Array Type="{x:Type x:String}">
|
||||
<x:String>Red</x:String>
|
||||
<x:String>Green</x:String>
|
||||
<x:String>Blue</x:String>
|
||||
<x:String>Yellow</x:String>
|
||||
<x:String>Purple</x:String>
|
||||
</x:Array>
|
||||
</Picker.ItemsSource>
|
||||
</Picker>
|
||||
|
||||
<!-- Styled picker -->
|
||||
<Label Text="Styled Picker:"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<Picker x:Name="SizePicker"
|
||||
Title="Select size"
|
||||
TextColor="{AppThemeBinding Light=DarkBlue, Dark=LightBlue}"
|
||||
TitleColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
SelectedIndexChanged="OnSizePickerChanged">
|
||||
<Picker.ItemsSource>
|
||||
<x:Array Type="{x:Type x:String}">
|
||||
<x:String>Small</x:String>
|
||||
<x:String>Medium</x:String>
|
||||
<x:String>Large</x:String>
|
||||
<x:String>Extra Large</x:String>
|
||||
</x:Array>
|
||||
</Picker.ItemsSource>
|
||||
</Picker>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- DatePicker Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="15">
|
||||
<Label Text="DatePicker"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Basic date picker -->
|
||||
<DatePicker x:Name="BasicDatePicker"
|
||||
DateSelected="OnDateSelected" />
|
||||
<Label x:Name="DateSelectedLabel"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Date picker with range -->
|
||||
<Label Text="With Date Range (this month only):"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<DatePicker x:Name="RangeDatePicker"
|
||||
DateSelected="OnRangeDateSelected" />
|
||||
|
||||
<!-- Styled date picker -->
|
||||
<Label Text="Styled DatePicker:"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<DatePicker x:Name="StyledDatePicker"
|
||||
TextColor="{AppThemeBinding Light=DarkGreen, Dark=LightGreen}"
|
||||
DateSelected="OnStyledDateSelected" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- TimePicker Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="15">
|
||||
<Label Text="TimePicker"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Basic time picker -->
|
||||
<TimePicker x:Name="BasicTimePicker"
|
||||
PropertyChanged="OnTimePickerPropertyChanged" />
|
||||
<Label x:Name="TimeSelectedLabel"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Styled time picker -->
|
||||
<Label Text="Styled TimePicker:"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<TimePicker x:Name="StyledTimePicker"
|
||||
Time="14:30:00"
|
||||
TextColor="{AppThemeBinding Light=DarkBlue, Dark=LightBlue}"
|
||||
PropertyChanged="OnStyledTimePickerPropertyChanged" />
|
||||
|
||||
<!-- Alarm time -->
|
||||
<Label Text="Alarm Time:"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<TimePicker x:Name="AlarmTimePicker" Time="07:00:00" />
|
||||
<Button Text="Set Alarm"
|
||||
BackgroundColor="{StaticResource WarningColor}"
|
||||
TextColor="White"
|
||||
Clicked="OnSetAlarmClicked" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- Event Log Panel -->
|
||||
<Border Grid.Row="1"
|
||||
BackgroundColor="{AppThemeBinding Light=#F5F5F5, Dark=#2C2C2C}"
|
||||
StrokeThickness="0"
|
||||
Padding="10">
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Event Log:"
|
||||
FontSize="12"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<ScrollView HeightRequest="80">
|
||||
<Label x:Name="EventLogLabel"
|
||||
Text="Events will appear here..."
|
||||
FontSize="11"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
LineBreakMode="WordWrap" />
|
||||
</ScrollView>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
107
ShellDemo/Pages/PickersPage.xaml.cs
Normal file
107
ShellDemo/Pages/PickersPage.xaml.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
// PickersPage - Picker, DatePicker, TimePicker Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class PickersPage : ContentPage
|
||||
{
|
||||
private int _eventCount = 0;
|
||||
|
||||
public PickersPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// Set up date picker with current date
|
||||
BasicDatePicker.Date = DateTime.Today;
|
||||
DateSelectedLabel.Text = $"Selected: {DateTime.Today:d}";
|
||||
|
||||
// Set up range date picker
|
||||
var startOfMonth = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
|
||||
var endOfMonth = startOfMonth.AddMonths(1).AddDays(-1);
|
||||
RangeDatePicker.MinimumDate = startOfMonth;
|
||||
RangeDatePicker.MaximumDate = endOfMonth;
|
||||
RangeDatePicker.Date = DateTime.Today;
|
||||
|
||||
// Set up styled date picker
|
||||
StyledDatePicker.Date = DateTime.Today.AddDays(7);
|
||||
|
||||
// Set up time picker
|
||||
BasicTimePicker.Time = DateTime.Now.TimeOfDay;
|
||||
TimeSelectedLabel.Text = $"Selected: {DateTime.Now:t}";
|
||||
}
|
||||
|
||||
private void OnFruitPickerChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (FruitPicker.SelectedIndex >= 0)
|
||||
{
|
||||
var item = FruitPicker.ItemsSource[FruitPicker.SelectedIndex]?.ToString();
|
||||
FruitSelectedLabel.Text = $"Selected: {item}";
|
||||
LogEvent($"Fruit selected: {item}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnColorPickerChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (ColorPicker.SelectedIndex >= 0)
|
||||
{
|
||||
var item = ColorPicker.ItemsSource[ColorPicker.SelectedIndex]?.ToString();
|
||||
LogEvent($"Color selected: {item}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSizePickerChanged(object? sender, EventArgs e)
|
||||
{
|
||||
if (SizePicker.SelectedIndex >= 0)
|
||||
{
|
||||
var item = SizePicker.ItemsSource[SizePicker.SelectedIndex]?.ToString();
|
||||
LogEvent($"Size selected: {item}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDateSelected(object? sender, DateChangedEventArgs e)
|
||||
{
|
||||
DateSelectedLabel.Text = $"Selected: {e.NewDate:d}";
|
||||
LogEvent($"Date selected: {e.NewDate:d}");
|
||||
}
|
||||
|
||||
private void OnRangeDateSelected(object? sender, DateChangedEventArgs e)
|
||||
{
|
||||
LogEvent($"Date (limited): {e.NewDate:d}");
|
||||
}
|
||||
|
||||
private void OnStyledDateSelected(object? sender, DateChangedEventArgs e)
|
||||
{
|
||||
LogEvent($"Styled date: {e.NewDate:d}");
|
||||
}
|
||||
|
||||
private void OnTimePickerPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(TimePicker.Time))
|
||||
{
|
||||
var time = BasicTimePicker.Time;
|
||||
TimeSelectedLabel.Text = $"Selected: {time:hh\\:mm}";
|
||||
LogEvent($"Time selected: {time:hh\\:mm}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnStyledTimePickerPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(TimePicker.Time))
|
||||
{
|
||||
LogEvent($"Styled time: {StyledTimePicker.Time:hh\\:mm}");
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSetAlarmClicked(object? sender, EventArgs e)
|
||||
{
|
||||
LogEvent($"Alarm set for {AlarmTimePicker.Time:hh\\:mm}");
|
||||
}
|
||||
|
||||
private void LogEvent(string message)
|
||||
{
|
||||
_eventCount++;
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
EventLogLabel.Text = $"[{timestamp}] {_eventCount}. {message}\n{EventLogLabel.Text}";
|
||||
}
|
||||
}
|
||||
@@ -1,261 +0,0 @@
|
||||
// ProgressPage - ProgressBar and ActivityIndicator Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public class ProgressPage : ContentPage
|
||||
{
|
||||
private readonly Label _eventLog;
|
||||
private int _eventCount = 0;
|
||||
private ProgressBar? _animatedProgress;
|
||||
private bool _isAnimating = false;
|
||||
|
||||
public ProgressPage()
|
||||
{
|
||||
Title = "Progress";
|
||||
|
||||
_eventLog = new Label
|
||||
{
|
||||
Text = "Events will appear here...",
|
||||
FontSize = 11,
|
||||
TextColor = Colors.Gray,
|
||||
LineBreakMode = LineBreakMode.WordWrap
|
||||
};
|
||||
|
||||
Content = new Grid
|
||||
{
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
|
||||
new RowDefinition { Height = new GridLength(120) }
|
||||
},
|
||||
Children =
|
||||
{
|
||||
CreateMainContent(),
|
||||
CreateEventLogPanel()
|
||||
}
|
||||
};
|
||||
|
||||
Grid.SetRow((View)((Grid)Content).Children[0], 0);
|
||||
Grid.SetRow((View)((Grid)Content).Children[1], 1);
|
||||
}
|
||||
|
||||
private View CreateMainContent()
|
||||
{
|
||||
return new ScrollView
|
||||
{
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = new Thickness(20),
|
||||
Spacing = 20,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "Progress Indicators", FontSize = 24, FontAttributes = FontAttributes.Bold },
|
||||
|
||||
CreateSection("ProgressBar", CreateProgressBarDemo()),
|
||||
CreateSection("ActivityIndicator", CreateActivityIndicatorDemo()),
|
||||
CreateSection("Interactive Demo", CreateInteractiveDemo())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateProgressBarDemo()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Various progress values
|
||||
var values = new[] { 0.0, 0.25, 0.5, 0.75, 1.0 };
|
||||
foreach (var value in values)
|
||||
{
|
||||
var row = new HorizontalStackLayout { Spacing = 10 };
|
||||
var progress = new ProgressBar { Progress = value, WidthRequest = 200 };
|
||||
var label = new Label { Text = $"{value * 100:0}%", VerticalOptions = LayoutOptions.Center, WidthRequest = 50 };
|
||||
row.Children.Add(progress);
|
||||
row.Children.Add(label);
|
||||
layout.Children.Add(row);
|
||||
}
|
||||
|
||||
// Colored progress bars
|
||||
layout.Children.Add(new Label { Text = "Colored Progress Bars:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
|
||||
var colors = new[] { Colors.Red, Colors.Green, Colors.Blue, Colors.Orange, Colors.Purple };
|
||||
foreach (var color in colors)
|
||||
{
|
||||
var progress = new ProgressBar { Progress = 0.7, ProgressColor = color };
|
||||
layout.Children.Add(progress);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateActivityIndicatorDemo()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Running indicator
|
||||
var runningRow = new HorizontalStackLayout { Spacing = 15 };
|
||||
var runningIndicator = new ActivityIndicator { IsRunning = true };
|
||||
runningRow.Children.Add(runningIndicator);
|
||||
runningRow.Children.Add(new Label { Text = "Loading...", VerticalOptions = LayoutOptions.Center });
|
||||
layout.Children.Add(runningRow);
|
||||
|
||||
// Toggle indicator
|
||||
var toggleRow = new HorizontalStackLayout { Spacing = 15 };
|
||||
var toggleIndicator = new ActivityIndicator { IsRunning = false };
|
||||
var toggleBtn = new Button { Text = "Start/Stop" };
|
||||
toggleBtn.Clicked += (s, e) =>
|
||||
{
|
||||
toggleIndicator.IsRunning = !toggleIndicator.IsRunning;
|
||||
LogEvent($"ActivityIndicator: {(toggleIndicator.IsRunning ? "Started" : "Stopped")}");
|
||||
};
|
||||
toggleRow.Children.Add(toggleIndicator);
|
||||
toggleRow.Children.Add(toggleBtn);
|
||||
layout.Children.Add(toggleRow);
|
||||
|
||||
// Colored indicators
|
||||
layout.Children.Add(new Label { Text = "Colored Indicators:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
var colorRow = new HorizontalStackLayout { Spacing = 20 };
|
||||
var indicatorColors = new[] { Colors.Red, Colors.Green, Colors.Blue, Colors.Orange };
|
||||
foreach (var color in indicatorColors)
|
||||
{
|
||||
var indicator = new ActivityIndicator { IsRunning = true, Color = color };
|
||||
colorRow.Children.Add(indicator);
|
||||
}
|
||||
layout.Children.Add(colorRow);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateInteractiveDemo()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Slider-controlled progress
|
||||
var progressLabel = new Label { Text = "Progress: 50%" };
|
||||
_animatedProgress = new ProgressBar { Progress = 0.5 };
|
||||
|
||||
var slider = new Slider { Minimum = 0, Maximum = 100, Value = 50 };
|
||||
slider.ValueChanged += (s, e) =>
|
||||
{
|
||||
var value = e.NewValue / 100.0;
|
||||
_animatedProgress.Progress = value;
|
||||
progressLabel.Text = $"Progress: {e.NewValue:0}%";
|
||||
};
|
||||
|
||||
layout.Children.Add(_animatedProgress);
|
||||
layout.Children.Add(slider);
|
||||
layout.Children.Add(progressLabel);
|
||||
|
||||
// Animated progress buttons
|
||||
var buttonRow = new HorizontalStackLayout { Spacing = 10, Margin = new Thickness(0, 10, 0, 0) };
|
||||
|
||||
var resetBtn = new Button { Text = "Reset", BackgroundColor = Colors.Gray, TextColor = Colors.White };
|
||||
resetBtn.Clicked += async (s, e) =>
|
||||
{
|
||||
_animatedProgress.Progress = 0;
|
||||
slider.Value = 0;
|
||||
LogEvent("Progress reset to 0%");
|
||||
};
|
||||
|
||||
var animateBtn = new Button { Text = "Animate to 100%", BackgroundColor = Colors.Blue, TextColor = Colors.White };
|
||||
animateBtn.Clicked += async (s, e) =>
|
||||
{
|
||||
if (_isAnimating) return;
|
||||
_isAnimating = true;
|
||||
LogEvent("Animation started");
|
||||
|
||||
for (int i = (int)(slider.Value); i <= 100; i += 5)
|
||||
{
|
||||
_animatedProgress.Progress = i / 100.0;
|
||||
slider.Value = i;
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
_isAnimating = false;
|
||||
LogEvent("Animation completed");
|
||||
};
|
||||
|
||||
var simulateBtn = new Button { Text = "Simulate Download", BackgroundColor = Colors.Green, TextColor = Colors.White };
|
||||
simulateBtn.Clicked += async (s, e) =>
|
||||
{
|
||||
if (_isAnimating) return;
|
||||
_isAnimating = true;
|
||||
LogEvent("Download simulation started");
|
||||
|
||||
_animatedProgress.Progress = 0;
|
||||
slider.Value = 0;
|
||||
|
||||
var random = new Random();
|
||||
double progress = 0;
|
||||
while (progress < 1.0)
|
||||
{
|
||||
progress += random.NextDouble() * 0.1;
|
||||
if (progress > 1.0) progress = 1.0;
|
||||
_animatedProgress.Progress = progress;
|
||||
slider.Value = progress * 100;
|
||||
await Task.Delay(200 + random.Next(300));
|
||||
}
|
||||
|
||||
_isAnimating = false;
|
||||
LogEvent("Download simulation completed");
|
||||
};
|
||||
|
||||
buttonRow.Children.Add(resetBtn);
|
||||
buttonRow.Children.Add(animateBtn);
|
||||
buttonRow.Children.Add(simulateBtn);
|
||||
layout.Children.Add(buttonRow);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private Frame CreateSection(string title, View content)
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
CornerRadius = 8,
|
||||
Padding = new Thickness(15),
|
||||
BackgroundColor = Colors.White,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = title, FontSize = 16, FontAttributes = FontAttributes.Bold },
|
||||
content
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateEventLogPanel()
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5"),
|
||||
Padding = new Thickness(10),
|
||||
CornerRadius = 0,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "Event Log:", FontSize = 12, FontAttributes = FontAttributes.Bold },
|
||||
new ScrollView
|
||||
{
|
||||
HeightRequest = 80,
|
||||
Content = _eventLog
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void LogEvent(string message)
|
||||
{
|
||||
_eventCount++;
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
_eventLog.Text = $"[{timestamp}] {_eventCount}. {message}\n{_eventLog.Text}";
|
||||
}
|
||||
}
|
||||
167
ShellDemo/Pages/ProgressPage.xaml
Normal file
167
ShellDemo/Pages/ProgressPage.xaml
Normal file
@@ -0,0 +1,167 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.ProgressPage"
|
||||
Title="Progress"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<Grid RowDefinitions="*,120">
|
||||
|
||||
<!-- Main Content -->
|
||||
<ScrollView Grid.Row="0">
|
||||
<VerticalStackLayout Padding="20" Spacing="20">
|
||||
|
||||
<Label Text="Progress Indicators"
|
||||
FontSize="24"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- ProgressBar Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="15">
|
||||
<Label Text="ProgressBar"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Various progress values -->
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<ProgressBar Progress="0" WidthRequest="200" />
|
||||
<Label Text="0%" VerticalOptions="Center" WidthRequest="50"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<ProgressBar Progress="0.25" WidthRequest="200" />
|
||||
<Label Text="25%" VerticalOptions="Center" WidthRequest="50"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<ProgressBar Progress="0.5" WidthRequest="200" />
|
||||
<Label Text="50%" VerticalOptions="Center" WidthRequest="50"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<ProgressBar Progress="0.75" WidthRequest="200" />
|
||||
<Label Text="75%" VerticalOptions="Center" WidthRequest="50"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<ProgressBar Progress="1.0" WidthRequest="200" />
|
||||
<Label Text="100%" VerticalOptions="Center" WidthRequest="50"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<!-- Colored progress bars -->
|
||||
<Label Text="Colored Progress Bars:"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
|
||||
<ProgressBar Progress="0.7" ProgressColor="Red" />
|
||||
<ProgressBar Progress="0.7" ProgressColor="Green" />
|
||||
<ProgressBar Progress="0.7" ProgressColor="Blue" />
|
||||
<ProgressBar Progress="0.7" ProgressColor="Orange" />
|
||||
<ProgressBar Progress="0.7" ProgressColor="Purple" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- ActivityIndicator Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="15">
|
||||
<Label Text="ActivityIndicator"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Running indicator -->
|
||||
<HorizontalStackLayout Spacing="15">
|
||||
<ActivityIndicator IsRunning="True" />
|
||||
<Label Text="Loading..." VerticalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<!-- Toggle indicator -->
|
||||
<HorizontalStackLayout Spacing="15">
|
||||
<ActivityIndicator x:Name="ToggleIndicator" IsRunning="False" />
|
||||
<Button Text="Start/Stop"
|
||||
Style="{StaticResource SecondaryButton}"
|
||||
Clicked="OnToggleIndicatorClicked" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<!-- Colored indicators -->
|
||||
<Label Text="Colored Indicators:"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<HorizontalStackLayout Spacing="20">
|
||||
<ActivityIndicator IsRunning="True" Color="Red" />
|
||||
<ActivityIndicator IsRunning="True" Color="Green" />
|
||||
<ActivityIndicator IsRunning="True" Color="Blue" />
|
||||
<ActivityIndicator IsRunning="True" Color="Orange" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Interactive Demo Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="15">
|
||||
<Label Text="Interactive Demo"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Slider-controlled progress -->
|
||||
<ProgressBar x:Name="AnimatedProgress" Progress="0.5" />
|
||||
<Slider x:Name="ProgressSlider"
|
||||
Minimum="0"
|
||||
Maximum="100"
|
||||
Value="50"
|
||||
ValueChanged="OnProgressSliderValueChanged" />
|
||||
<Label x:Name="ProgressLabel"
|
||||
Text="Progress: 50%"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Animated progress buttons -->
|
||||
<HorizontalStackLayout Spacing="10" Margin="0,10,0,0">
|
||||
<Button Text="Reset"
|
||||
Style="{StaticResource SecondaryButton}"
|
||||
Clicked="OnResetClicked" />
|
||||
<Button Text="Animate to 100%"
|
||||
Style="{StaticResource PrimaryButton}"
|
||||
Clicked="OnAnimateClicked" />
|
||||
<Button Text="Simulate Download"
|
||||
Style="{StaticResource SuccessButton}"
|
||||
Clicked="OnSimulateDownloadClicked" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- Event Log Panel -->
|
||||
<Border Grid.Row="1"
|
||||
BackgroundColor="{AppThemeBinding Light=#F5F5F5, Dark=#2C2C2C}"
|
||||
StrokeThickness="0"
|
||||
Padding="10">
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Event Log:"
|
||||
FontSize="12"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<ScrollView HeightRequest="80">
|
||||
<Label x:Name="EventLogLabel"
|
||||
Text="Events will appear here..."
|
||||
FontSize="11"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
LineBreakMode="WordWrap" />
|
||||
</ScrollView>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
83
ShellDemo/Pages/ProgressPage.xaml.cs
Normal file
83
ShellDemo/Pages/ProgressPage.xaml.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
// ProgressPage - ProgressBar and ActivityIndicator Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class ProgressPage : ContentPage
|
||||
{
|
||||
private int _eventCount = 0;
|
||||
private bool _isAnimating = false;
|
||||
|
||||
public ProgressPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnToggleIndicatorClicked(object? sender, EventArgs e)
|
||||
{
|
||||
ToggleIndicator.IsRunning = !ToggleIndicator.IsRunning;
|
||||
LogEvent($"ActivityIndicator: {(ToggleIndicator.IsRunning ? "Started" : "Stopped")}");
|
||||
}
|
||||
|
||||
private void OnProgressSliderValueChanged(object? sender, ValueChangedEventArgs e)
|
||||
{
|
||||
AnimatedProgress.Progress = e.NewValue / 100.0;
|
||||
ProgressLabel.Text = $"Progress: {(int)e.NewValue}%";
|
||||
}
|
||||
|
||||
private void OnResetClicked(object? sender, EventArgs e)
|
||||
{
|
||||
AnimatedProgress.Progress = 0;
|
||||
ProgressSlider.Value = 0;
|
||||
LogEvent("Progress reset to 0%");
|
||||
}
|
||||
|
||||
private async void OnAnimateClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (_isAnimating) return;
|
||||
_isAnimating = true;
|
||||
LogEvent("Animation started");
|
||||
|
||||
for (int i = (int)ProgressSlider.Value; i <= 100; i += 5)
|
||||
{
|
||||
AnimatedProgress.Progress = i / 100.0;
|
||||
ProgressSlider.Value = i;
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
_isAnimating = false;
|
||||
LogEvent("Animation completed");
|
||||
}
|
||||
|
||||
private async void OnSimulateDownloadClicked(object? sender, EventArgs e)
|
||||
{
|
||||
if (_isAnimating) return;
|
||||
_isAnimating = true;
|
||||
LogEvent("Download simulation started");
|
||||
|
||||
AnimatedProgress.Progress = 0;
|
||||
ProgressSlider.Value = 0;
|
||||
|
||||
var random = new Random();
|
||||
double progress = 0;
|
||||
while (progress < 1.0)
|
||||
{
|
||||
progress += random.NextDouble() * 0.1;
|
||||
if (progress > 1.0) progress = 1.0;
|
||||
AnimatedProgress.Progress = progress;
|
||||
ProgressSlider.Value = progress * 100;
|
||||
await Task.Delay(200 + random.Next(300));
|
||||
}
|
||||
|
||||
_isAnimating = false;
|
||||
LogEvent("Download simulation completed");
|
||||
}
|
||||
|
||||
private void LogEvent(string message)
|
||||
{
|
||||
_eventCount++;
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
EventLogLabel.Text = $"[{timestamp}] {_eventCount}. {message}\n{EventLogLabel.Text}";
|
||||
}
|
||||
}
|
||||
@@ -1,239 +0,0 @@
|
||||
// SelectionPage - CheckBox, Switch, Slider Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public class SelectionPage : ContentPage
|
||||
{
|
||||
private readonly Label _eventLog;
|
||||
private int _eventCount = 0;
|
||||
|
||||
public SelectionPage()
|
||||
{
|
||||
Title = "Selection Controls";
|
||||
|
||||
_eventLog = new Label
|
||||
{
|
||||
Text = "Events will appear here...",
|
||||
FontSize = 11,
|
||||
TextColor = Colors.Gray,
|
||||
LineBreakMode = LineBreakMode.WordWrap
|
||||
};
|
||||
|
||||
Content = new Grid
|
||||
{
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
|
||||
new RowDefinition { Height = new GridLength(120) }
|
||||
},
|
||||
Children =
|
||||
{
|
||||
CreateMainContent(),
|
||||
CreateEventLogPanel()
|
||||
}
|
||||
};
|
||||
|
||||
Grid.SetRow((View)((Grid)Content).Children[0], 0);
|
||||
Grid.SetRow((View)((Grid)Content).Children[1], 1);
|
||||
}
|
||||
|
||||
private View CreateMainContent()
|
||||
{
|
||||
return new ScrollView
|
||||
{
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = new Thickness(20),
|
||||
Spacing = 20,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "Selection Controls", FontSize = 24, FontAttributes = FontAttributes.Bold },
|
||||
|
||||
CreateSection("CheckBox", CreateCheckBoxDemo()),
|
||||
CreateSection("Switch", CreateSwitchDemo()),
|
||||
CreateSection("Slider", CreateSliderDemo())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateCheckBoxDemo()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Basic checkboxes
|
||||
var basicRow = new HorizontalStackLayout { Spacing = 20 };
|
||||
|
||||
var cb1 = new CheckBox { IsChecked = false };
|
||||
cb1.CheckedChanged += (s, e) => LogEvent($"Checkbox 1: {(e.Value ? "Checked" : "Unchecked")}");
|
||||
basicRow.Children.Add(cb1);
|
||||
basicRow.Children.Add(new Label { Text = "Option 1", VerticalOptions = LayoutOptions.Center });
|
||||
|
||||
var cb2 = new CheckBox { IsChecked = true };
|
||||
cb2.CheckedChanged += (s, e) => LogEvent($"Checkbox 2: {(e.Value ? "Checked" : "Unchecked")}");
|
||||
basicRow.Children.Add(cb2);
|
||||
basicRow.Children.Add(new Label { Text = "Option 2 (default checked)", VerticalOptions = LayoutOptions.Center });
|
||||
|
||||
layout.Children.Add(basicRow);
|
||||
|
||||
// Colored checkboxes
|
||||
var colorRow = new HorizontalStackLayout { Spacing = 20 };
|
||||
var colors = new[] { Colors.Red, Colors.Green, Colors.Blue, Colors.Purple };
|
||||
foreach (var color in colors)
|
||||
{
|
||||
var cb = new CheckBox { Color = color, IsChecked = true };
|
||||
cb.CheckedChanged += (s, e) => LogEvent($"{color} checkbox: {(e.Value ? "Checked" : "Unchecked")}");
|
||||
colorRow.Children.Add(cb);
|
||||
}
|
||||
layout.Children.Add(new Label { Text = "Colored Checkboxes:", FontSize = 12 });
|
||||
layout.Children.Add(colorRow);
|
||||
|
||||
// Disabled checkbox
|
||||
var disabledRow = new HorizontalStackLayout { Spacing = 10 };
|
||||
var disabledCb = new CheckBox { IsChecked = true, IsEnabled = false };
|
||||
disabledRow.Children.Add(disabledCb);
|
||||
disabledRow.Children.Add(new Label { Text = "Disabled (checked)", VerticalOptions = LayoutOptions.Center, TextColor = Colors.Gray });
|
||||
layout.Children.Add(disabledRow);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateSwitchDemo()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Basic switch
|
||||
var basicRow = new HorizontalStackLayout { Spacing = 15 };
|
||||
var statusLabel = new Label { Text = "Off", VerticalOptions = LayoutOptions.Center, WidthRequest = 50 };
|
||||
var sw1 = new Switch { IsToggled = false };
|
||||
sw1.Toggled += (s, e) =>
|
||||
{
|
||||
statusLabel.Text = e.Value ? "On" : "Off";
|
||||
LogEvent($"Switch toggled: {(e.Value ? "ON" : "OFF")}");
|
||||
};
|
||||
basicRow.Children.Add(sw1);
|
||||
basicRow.Children.Add(statusLabel);
|
||||
layout.Children.Add(basicRow);
|
||||
|
||||
// Colored switches
|
||||
var colorRow = new HorizontalStackLayout { Spacing = 20 };
|
||||
var switchColors = new[] { Colors.Green, Colors.Orange, Colors.Purple };
|
||||
foreach (var color in switchColors)
|
||||
{
|
||||
var sw = new Switch { IsToggled = true, OnColor = color };
|
||||
sw.Toggled += (s, e) => LogEvent($"{color} switch: {(e.Value ? "ON" : "OFF")}");
|
||||
colorRow.Children.Add(sw);
|
||||
}
|
||||
layout.Children.Add(new Label { Text = "Colored Switches:", FontSize = 12 });
|
||||
layout.Children.Add(colorRow);
|
||||
|
||||
// Disabled switch
|
||||
var disabledRow = new HorizontalStackLayout { Spacing = 10 };
|
||||
var disabledSw = new Switch { IsToggled = true, IsEnabled = false };
|
||||
disabledRow.Children.Add(disabledSw);
|
||||
disabledRow.Children.Add(new Label { Text = "Disabled (on)", VerticalOptions = LayoutOptions.Center, TextColor = Colors.Gray });
|
||||
layout.Children.Add(disabledRow);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private View CreateSliderDemo()
|
||||
{
|
||||
var layout = new VerticalStackLayout { Spacing = 15 };
|
||||
|
||||
// Basic slider
|
||||
var valueLabel = new Label { Text = "Value: 50" };
|
||||
var slider1 = new Slider { Minimum = 0, Maximum = 100, Value = 50 };
|
||||
slider1.ValueChanged += (s, e) =>
|
||||
{
|
||||
valueLabel.Text = $"Value: {(int)e.NewValue}";
|
||||
LogEvent($"Slider value: {(int)e.NewValue}");
|
||||
};
|
||||
layout.Children.Add(slider1);
|
||||
layout.Children.Add(valueLabel);
|
||||
|
||||
// Slider with custom range
|
||||
layout.Children.Add(new Label { Text = "Temperature (0-40°C):", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
var tempLabel = new Label { Text = "20°C" };
|
||||
var tempSlider = new Slider { Minimum = 0, Maximum = 40, Value = 20 };
|
||||
tempSlider.ValueChanged += (s, e) =>
|
||||
{
|
||||
tempLabel.Text = $"{(int)e.NewValue}°C";
|
||||
LogEvent($"Temperature: {(int)e.NewValue}°C");
|
||||
};
|
||||
layout.Children.Add(tempSlider);
|
||||
layout.Children.Add(tempLabel);
|
||||
|
||||
// Colored slider
|
||||
layout.Children.Add(new Label { Text = "Colored Slider:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
var colorSlider = new Slider
|
||||
{
|
||||
Minimum = 0,
|
||||
Maximum = 100,
|
||||
Value = 75,
|
||||
MinimumTrackColor = Colors.Green,
|
||||
MaximumTrackColor = Colors.LightGray,
|
||||
ThumbColor = Colors.DarkGreen
|
||||
};
|
||||
colorSlider.ValueChanged += (s, e) => LogEvent($"Colored slider: {(int)e.NewValue}");
|
||||
layout.Children.Add(colorSlider);
|
||||
|
||||
// Disabled slider
|
||||
layout.Children.Add(new Label { Text = "Disabled Slider:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
|
||||
var disabledSlider = new Slider { Minimum = 0, Maximum = 100, Value = 30, IsEnabled = false };
|
||||
layout.Children.Add(disabledSlider);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private Frame CreateSection(string title, View content)
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
CornerRadius = 8,
|
||||
Padding = new Thickness(15),
|
||||
BackgroundColor = Colors.White,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 10,
|
||||
Children =
|
||||
{
|
||||
new Label { Text = title, FontSize = 16, FontAttributes = FontAttributes.Bold },
|
||||
content
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private View CreateEventLogPanel()
|
||||
{
|
||||
return new Frame
|
||||
{
|
||||
BackgroundColor = Color.FromArgb("#F5F5F5"),
|
||||
Padding = new Thickness(10),
|
||||
CornerRadius = 0,
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label { Text = "Event Log:", FontSize = 12, FontAttributes = FontAttributes.Bold },
|
||||
new ScrollView
|
||||
{
|
||||
HeightRequest = 80,
|
||||
Content = _eventLog
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void LogEvent(string message)
|
||||
{
|
||||
_eventCount++;
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
_eventLog.Text = $"[{timestamp}] {_eventCount}. {message}\n{_eventLog.Text}";
|
||||
}
|
||||
}
|
||||
157
ShellDemo/Pages/SelectionPage.xaml
Normal file
157
ShellDemo/Pages/SelectionPage.xaml
Normal file
@@ -0,0 +1,157 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.SelectionPage"
|
||||
Title="Selection Controls"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<Grid RowDefinitions="*,120">
|
||||
|
||||
<!-- Main Content -->
|
||||
<ScrollView Grid.Row="0">
|
||||
<VerticalStackLayout Padding="20" Spacing="20">
|
||||
|
||||
<Label Text="Selection Controls"
|
||||
FontSize="24"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- CheckBox Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="15">
|
||||
<Label Text="CheckBox"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Basic checkboxes -->
|
||||
<HorizontalStackLayout Spacing="20">
|
||||
<CheckBox x:Name="Checkbox1" IsChecked="False" CheckedChanged="OnCheckboxChanged" />
|
||||
<Label Text="Option 1" VerticalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<CheckBox x:Name="Checkbox2" IsChecked="True" CheckedChanged="OnCheckboxChanged" />
|
||||
<Label Text="Option 2 (default checked)" VerticalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<!-- Colored checkboxes -->
|
||||
<Label Text="Colored Checkboxes:"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<HorizontalStackLayout Spacing="20">
|
||||
<CheckBox Color="Red" IsChecked="True" CheckedChanged="OnColoredCheckboxChanged" />
|
||||
<CheckBox Color="Green" IsChecked="True" CheckedChanged="OnColoredCheckboxChanged" />
|
||||
<CheckBox Color="Blue" IsChecked="True" CheckedChanged="OnColoredCheckboxChanged" />
|
||||
<CheckBox Color="Purple" IsChecked="True" CheckedChanged="OnColoredCheckboxChanged" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<!-- Disabled checkbox -->
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<CheckBox IsChecked="True" IsEnabled="False" />
|
||||
<Label Text="Disabled (checked)" VerticalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Switch Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="15">
|
||||
<Label Text="Switch"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Basic switch -->
|
||||
<HorizontalStackLayout Spacing="15">
|
||||
<Switch x:Name="BasicSwitch" IsToggled="False" Toggled="OnSwitchToggled" />
|
||||
<Label x:Name="SwitchStatusLabel" Text="Off" VerticalOptions="Center" WidthRequest="50"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<!-- Colored switches -->
|
||||
<Label Text="Colored Switches:"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<HorizontalStackLayout Spacing="20">
|
||||
<Switch IsToggled="True" OnColor="Green" Toggled="OnColoredSwitchToggled" />
|
||||
<Switch IsToggled="True" OnColor="Orange" Toggled="OnColoredSwitchToggled" />
|
||||
<Switch IsToggled="True" OnColor="Purple" Toggled="OnColoredSwitchToggled" />
|
||||
</HorizontalStackLayout>
|
||||
|
||||
<!-- Disabled switch -->
|
||||
<HorizontalStackLayout Spacing="10">
|
||||
<Switch IsToggled="True" IsEnabled="False" />
|
||||
<Label Text="Disabled (on)" VerticalOptions="Center"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
</HorizontalStackLayout>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Slider Section -->
|
||||
<Border Style="{StaticResource ThemedCard}">
|
||||
<VerticalStackLayout Spacing="15">
|
||||
<Label Text="Slider"
|
||||
FontSize="16"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Basic slider -->
|
||||
<Slider x:Name="BasicSlider" Minimum="0" Maximum="100" Value="50" ValueChanged="OnSliderValueChanged" />
|
||||
<Label x:Name="SliderValueLabel" Text="Value: 50"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Temperature slider -->
|
||||
<Label Text="Temperature (0-40°C):"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<Slider x:Name="TempSlider" Minimum="0" Maximum="40" Value="20" ValueChanged="OnTempSliderValueChanged" />
|
||||
<Label x:Name="TempLabel" Text="20°C"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<!-- Colored slider -->
|
||||
<Label Text="Colored Slider:"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<Slider Minimum="0" Maximum="100" Value="75"
|
||||
MinimumTrackColor="Green"
|
||||
MaximumTrackColor="LightGray"
|
||||
ThumbColor="DarkGreen"
|
||||
ValueChanged="OnColoredSliderValueChanged" />
|
||||
|
||||
<!-- Disabled slider -->
|
||||
<Label Text="Disabled Slider:"
|
||||
FontSize="12"
|
||||
Margin="0,10,0,0"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
<Slider Minimum="0" Maximum="100" Value="30" IsEnabled="False" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
|
||||
<!-- Event Log Panel -->
|
||||
<Border Grid.Row="1"
|
||||
BackgroundColor="{AppThemeBinding Light=#F5F5F5, Dark=#2C2C2C}"
|
||||
StrokeThickness="0"
|
||||
Padding="10">
|
||||
<VerticalStackLayout>
|
||||
<Label Text="Event Log:"
|
||||
FontSize="12"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<ScrollView HeightRequest="80">
|
||||
<Label x:Name="EventLogLabel"
|
||||
Text="Events will appear here..."
|
||||
FontSize="11"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}"
|
||||
LineBreakMode="WordWrap" />
|
||||
</ScrollView>
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
65
ShellDemo/Pages/SelectionPage.xaml.cs
Normal file
65
ShellDemo/Pages/SelectionPage.xaml.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
// SelectionPage - CheckBox, Switch, Slider Demo
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class SelectionPage : ContentPage
|
||||
{
|
||||
private int _eventCount = 0;
|
||||
|
||||
public SelectionPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnCheckboxChanged(object? sender, CheckedChangedEventArgs e)
|
||||
{
|
||||
if (sender == Checkbox1)
|
||||
LogEvent($"Checkbox 1: {(e.Value ? "Checked" : "Unchecked")}");
|
||||
else if (sender == Checkbox2)
|
||||
LogEvent($"Checkbox 2: {(e.Value ? "Checked" : "Unchecked")}");
|
||||
}
|
||||
|
||||
private void OnColoredCheckboxChanged(object? sender, CheckedChangedEventArgs e)
|
||||
{
|
||||
if (sender is CheckBox cb)
|
||||
LogEvent($"{cb.Color} checkbox: {(e.Value ? "Checked" : "Unchecked")}");
|
||||
}
|
||||
|
||||
private void OnSwitchToggled(object? sender, ToggledEventArgs e)
|
||||
{
|
||||
SwitchStatusLabel.Text = e.Value ? "On" : "Off";
|
||||
LogEvent($"Switch toggled: {(e.Value ? "ON" : "OFF")}");
|
||||
}
|
||||
|
||||
private void OnColoredSwitchToggled(object? sender, ToggledEventArgs e)
|
||||
{
|
||||
if (sender is Switch sw)
|
||||
LogEvent($"{sw.OnColor} switch: {(e.Value ? "ON" : "OFF")}");
|
||||
}
|
||||
|
||||
private void OnSliderValueChanged(object? sender, ValueChangedEventArgs e)
|
||||
{
|
||||
SliderValueLabel.Text = $"Value: {(int)e.NewValue}";
|
||||
LogEvent($"Slider value: {(int)e.NewValue}");
|
||||
}
|
||||
|
||||
private void OnTempSliderValueChanged(object? sender, ValueChangedEventArgs e)
|
||||
{
|
||||
TempLabel.Text = $"{(int)e.NewValue}°C";
|
||||
LogEvent($"Temperature: {(int)e.NewValue}°C");
|
||||
}
|
||||
|
||||
private void OnColoredSliderValueChanged(object? sender, ValueChangedEventArgs e)
|
||||
{
|
||||
LogEvent($"Colored slider: {(int)e.NewValue}");
|
||||
}
|
||||
|
||||
private void LogEvent(string message)
|
||||
{
|
||||
_eventCount++;
|
||||
var timestamp = DateTime.Now.ToString("HH:mm:ss");
|
||||
EventLogLabel.Text = $"[{timestamp}] {_eventCount}. {message}\n{EventLogLabel.Text}";
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
// TextInputPage - Demonstrates text input controls
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Graphics;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public class TextInputPage : ContentPage
|
||||
{
|
||||
private Label _entryOutput;
|
||||
private Label _searchOutput;
|
||||
private Label _editorOutput;
|
||||
|
||||
public TextInputPage()
|
||||
{
|
||||
Title = "Text Input";
|
||||
|
||||
_entryOutput = new Label { TextColor = Colors.Gray, FontSize = 12 };
|
||||
_searchOutput = new Label { TextColor = Colors.Gray, FontSize = 12 };
|
||||
_editorOutput = new Label { TextColor = Colors.Gray, FontSize = 12 };
|
||||
|
||||
Content = new ScrollView
|
||||
{
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = new Thickness(20),
|
||||
Spacing = 15,
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = "Text Input Controls",
|
||||
FontSize = 24,
|
||||
FontAttributes = FontAttributes.Bold
|
||||
},
|
||||
new Label
|
||||
{
|
||||
Text = "Click on any field and start typing. All keyboard input is handled by the framework.",
|
||||
FontSize = 14,
|
||||
TextColor = Colors.Gray
|
||||
},
|
||||
|
||||
// Entry Section
|
||||
new BoxView { HeightRequest = 1, Color = Colors.LightGray },
|
||||
new Label { Text = "Entry (Single Line)", FontSize = 18, FontAttributes = FontAttributes.Bold },
|
||||
CreateEntry("Enter your name...", e => _entryOutput.Text = $"You typed: {e.Text}"),
|
||||
_entryOutput,
|
||||
|
||||
CreateEntry("Enter your email...", null, Keyboard.Email),
|
||||
new Label { Text = "Email keyboard type", FontSize = 12, TextColor = Colors.Gray },
|
||||
|
||||
CreatePasswordEntry("Enter password..."),
|
||||
new Label { Text = "Password field (text hidden)", FontSize = 12, TextColor = Colors.Gray },
|
||||
|
||||
// SearchBar Section
|
||||
new BoxView { HeightRequest = 1, Color = Colors.LightGray },
|
||||
new Label { Text = "SearchBar", FontSize = 18, FontAttributes = FontAttributes.Bold },
|
||||
CreateSearchBar(),
|
||||
_searchOutput,
|
||||
|
||||
// Editor Section
|
||||
new BoxView { HeightRequest = 1, Color = Colors.LightGray },
|
||||
new Label { Text = "Editor (Multi-line)", FontSize = 18, FontAttributes = FontAttributes.Bold },
|
||||
CreateEditor(),
|
||||
_editorOutput,
|
||||
|
||||
// Instructions
|
||||
new BoxView { HeightRequest = 1, Color = Colors.LightGray },
|
||||
new Frame
|
||||
{
|
||||
BackgroundColor = Color.FromArgb("#E3F2FD"),
|
||||
CornerRadius = 8,
|
||||
Padding = new Thickness(15),
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Spacing = 5,
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = "Keyboard Shortcuts",
|
||||
FontAttributes = FontAttributes.Bold
|
||||
},
|
||||
new Label { Text = "Ctrl+A: Select all" },
|
||||
new Label { Text = "Ctrl+C: Copy" },
|
||||
new Label { Text = "Ctrl+V: Paste" },
|
||||
new Label { Text = "Ctrl+X: Cut" },
|
||||
new Label { Text = "Home/End: Move to start/end" },
|
||||
new Label { Text = "Shift+Arrow: Select text" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private Entry CreateEntry(string placeholder, Action<Entry>? onTextChanged, Keyboard? keyboard = null)
|
||||
{
|
||||
var entry = new Entry
|
||||
{
|
||||
Placeholder = placeholder,
|
||||
FontSize = 14
|
||||
};
|
||||
|
||||
if (keyboard != null)
|
||||
{
|
||||
entry.Keyboard = keyboard;
|
||||
}
|
||||
|
||||
if (onTextChanged != null)
|
||||
{
|
||||
entry.TextChanged += (s, e) => onTextChanged(entry);
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
private Entry CreatePasswordEntry(string placeholder)
|
||||
{
|
||||
return new Entry
|
||||
{
|
||||
Placeholder = placeholder,
|
||||
FontSize = 14,
|
||||
IsPassword = true
|
||||
};
|
||||
}
|
||||
|
||||
private SearchBar CreateSearchBar()
|
||||
{
|
||||
var searchBar = new SearchBar
|
||||
{
|
||||
Placeholder = "Search for items..."
|
||||
};
|
||||
|
||||
searchBar.TextChanged += (s, e) =>
|
||||
{
|
||||
_searchOutput.Text = $"Searching: {e.NewTextValue}";
|
||||
};
|
||||
|
||||
searchBar.SearchButtonPressed += (s, e) =>
|
||||
{
|
||||
_searchOutput.Text = $"Search submitted: {searchBar.Text}";
|
||||
};
|
||||
|
||||
return searchBar;
|
||||
}
|
||||
|
||||
private Editor CreateEditor()
|
||||
{
|
||||
var editor = new Editor
|
||||
{
|
||||
Placeholder = "Enter multiple lines of text here...\nPress Enter to create new lines.",
|
||||
HeightRequest = 120,
|
||||
FontSize = 14
|
||||
};
|
||||
|
||||
editor.TextChanged += (s, e) =>
|
||||
{
|
||||
var lineCount = string.IsNullOrEmpty(e.NewTextValue) ? 0 : e.NewTextValue.Split('\n').Length;
|
||||
_editorOutput.Text = $"Lines: {lineCount}, Characters: {e.NewTextValue?.Length ?? 0}";
|
||||
};
|
||||
|
||||
return editor;
|
||||
}
|
||||
}
|
||||
121
ShellDemo/Pages/TextInputPage.xaml
Normal file
121
ShellDemo/Pages/TextInputPage.xaml
Normal file
@@ -0,0 +1,121 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="ShellDemo.TextInputPage"
|
||||
Title="Text Input"
|
||||
BackgroundColor="{AppThemeBinding Light={StaticResource PageBackgroundLight}, Dark={StaticResource PageBackgroundDark}}">
|
||||
|
||||
<ScrollView>
|
||||
<VerticalStackLayout Padding="20" Spacing="15">
|
||||
|
||||
<Label Text="Text Input Controls"
|
||||
FontSize="24"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<Label Text="Click on any field and start typing. All keyboard input is handled by the framework."
|
||||
FontSize="14"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
|
||||
<!-- Entry Section -->
|
||||
<BoxView Style="{StaticResource ThemedDivider}" />
|
||||
|
||||
<Label Text="Entry (Single Line)"
|
||||
FontSize="18"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<Entry x:Name="NameEntry"
|
||||
Placeholder="Enter your name..."
|
||||
Style="{StaticResource ThemedEntry}"
|
||||
TextChanged="OnNameEntryTextChanged" />
|
||||
|
||||
<Label x:Name="EntryOutputLabel"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
|
||||
<Entry x:Name="EmailEntry"
|
||||
Placeholder="Enter your email..."
|
||||
Keyboard="Email"
|
||||
Style="{StaticResource ThemedEntry}" />
|
||||
|
||||
<Label Text="Email keyboard type"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
|
||||
<Entry x:Name="PasswordEntry"
|
||||
Placeholder="Enter password..."
|
||||
IsPassword="True"
|
||||
Style="{StaticResource ThemedEntry}" />
|
||||
|
||||
<Label Text="Password field (text hidden)"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
|
||||
<!-- SearchBar Section -->
|
||||
<BoxView Style="{StaticResource ThemedDivider}" />
|
||||
|
||||
<Label Text="SearchBar"
|
||||
FontSize="18"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<SearchBar x:Name="MainSearchBar"
|
||||
Placeholder="Search for items..."
|
||||
TextChanged="OnSearchBarTextChanged"
|
||||
SearchButtonPressed="OnSearchButtonPressed" />
|
||||
|
||||
<Label x:Name="SearchOutputLabel"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
|
||||
<!-- Editor Section -->
|
||||
<BoxView Style="{StaticResource ThemedDivider}" />
|
||||
|
||||
<Label Text="Editor (Multi-line)"
|
||||
FontSize="18"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
|
||||
<Editor x:Name="MainEditor"
|
||||
Placeholder="Enter multiple lines of text here... Press Enter to create new lines."
|
||||
HeightRequest="120"
|
||||
Style="{StaticResource ThemedEditor}"
|
||||
TextChanged="OnEditorTextChanged" />
|
||||
|
||||
<Label x:Name="EditorOutputLabel"
|
||||
FontSize="12"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextSecondaryLight}, Dark={StaticResource TextSecondaryDark}}" />
|
||||
|
||||
<!-- Keyboard Shortcuts -->
|
||||
<BoxView Style="{StaticResource ThemedDivider}" />
|
||||
|
||||
<Border BackgroundColor="{AppThemeBinding Light=#E3F2FD, Dark=#1A3A5C}"
|
||||
StrokeThickness="0"
|
||||
Padding="15">
|
||||
<Border.StrokeShape>
|
||||
<RoundRectangle CornerRadius="8" />
|
||||
</Border.StrokeShape>
|
||||
|
||||
<VerticalStackLayout Spacing="5">
|
||||
<Label Text="Keyboard Shortcuts"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Label Text="Ctrl+A: Select all"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Label Text="Ctrl+C: Copy"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Label Text="Ctrl+V: Paste"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Label Text="Ctrl+X: Cut"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Label Text="Home/End: Move to start/end"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
<Label Text="Shift+Arrow: Select text"
|
||||
TextColor="{AppThemeBinding Light={StaticResource TextPrimaryLight}, Dark={StaticResource TextPrimaryDark}}" />
|
||||
</VerticalStackLayout>
|
||||
</Border>
|
||||
|
||||
</VerticalStackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
||||
34
ShellDemo/Pages/TextInputPage.xaml.cs
Normal file
34
ShellDemo/Pages/TextInputPage.xaml.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
// TextInputPage - Demonstrates text input controls
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
public partial class TextInputPage : ContentPage
|
||||
{
|
||||
public TextInputPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void OnNameEntryTextChanged(object? sender, TextChangedEventArgs e)
|
||||
{
|
||||
EntryOutputLabel.Text = $"You typed: {e.NewTextValue}";
|
||||
}
|
||||
|
||||
private void OnSearchBarTextChanged(object? sender, TextChangedEventArgs e)
|
||||
{
|
||||
SearchOutputLabel.Text = $"Searching: {e.NewTextValue}";
|
||||
}
|
||||
|
||||
private void OnSearchButtonPressed(object? sender, EventArgs e)
|
||||
{
|
||||
SearchOutputLabel.Text = $"Search submitted: {MainSearchBar.Text}";
|
||||
}
|
||||
|
||||
private void OnEditorTextChanged(object? sender, TextChangedEventArgs e)
|
||||
{
|
||||
var lineCount = string.IsNullOrEmpty(e.NewTextValue) ? 0 : e.NewTextValue.Split('\n').Length;
|
||||
EditorOutputLabel.Text = $"Lines: {lineCount}, Characters: {e.NewTextValue?.Length ?? 0}";
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
// Platforms/Linux/Program.cs - Linux platform entry point
|
||||
// Same pattern as Android's MainActivity or iOS's AppDelegate
|
||||
|
||||
using Microsoft.Maui.Platform.Linux;
|
||||
using Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// Create the shared MAUI app
|
||||
var app = MauiProgram.CreateMauiApp();
|
||||
|
||||
// Run on Linux platform
|
||||
LinuxApplication.Run(app, args);
|
||||
}
|
||||
}
|
||||
67
ShellDemo/Program.cs
Normal file
67
ShellDemo/Program.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
// Program.cs - Linux platform entry point
|
||||
|
||||
using Microsoft.Maui.Platform.Linux;
|
||||
|
||||
namespace ShellDemo;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// Redirect console output to a log file for debugging
|
||||
var logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "shelldemo.log");
|
||||
using var logWriter = new StreamWriter(logPath, append: false) { AutoFlush = true };
|
||||
var multiWriter = new MultiTextWriter(Console.Out, logWriter);
|
||||
Console.SetOut(multiWriter);
|
||||
Console.SetError(multiWriter);
|
||||
|
||||
// Global exception handler
|
||||
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
|
||||
{
|
||||
var ex = e.ExceptionObject as Exception;
|
||||
Console.WriteLine($"[FATAL] Unhandled exception: {ex?.GetType().Name}: {ex?.Message}");
|
||||
Console.WriteLine($"[FATAL] Stack trace: {ex?.StackTrace}");
|
||||
if (ex?.InnerException != null)
|
||||
{
|
||||
Console.WriteLine($"[FATAL] Inner exception: {ex.InnerException.GetType().Name}: {ex.InnerException.Message}");
|
||||
Console.WriteLine($"[FATAL] Inner stack trace: {ex.InnerException.StackTrace}");
|
||||
}
|
||||
};
|
||||
|
||||
TaskScheduler.UnobservedTaskException += (sender, e) =>
|
||||
{
|
||||
Console.WriteLine($"[FATAL] Unobserved task exception: {e.Exception?.GetType().Name}: {e.Exception?.Message}");
|
||||
Console.WriteLine($"[FATAL] Stack trace: {e.Exception?.StackTrace}");
|
||||
e.SetObserved(); // Prevent crash
|
||||
};
|
||||
|
||||
Console.WriteLine($"[Program] Starting Shell Demo at {DateTime.Now}");
|
||||
Console.WriteLine($"[Program] Log file: {logPath}");
|
||||
|
||||
try
|
||||
{
|
||||
// Create the MAUI app with all handlers registered
|
||||
var app = MauiProgram.CreateMauiApp();
|
||||
|
||||
// Run on Linux platform
|
||||
LinuxApplication.Run(app, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine($"[FATAL] Exception in Main: {ex.GetType().Name}: {ex.Message}");
|
||||
Console.WriteLine($"[FATAL] Stack trace: {ex.StackTrace}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to write to both console and file
|
||||
class MultiTextWriter : TextWriter
|
||||
{
|
||||
private readonly TextWriter[] _writers;
|
||||
public MultiTextWriter(params TextWriter[] writers) => _writers = writers;
|
||||
public override System.Text.Encoding Encoding => System.Text.Encoding.UTF8;
|
||||
public override void Write(char value) { foreach (var w in _writers) w.Write(value); }
|
||||
public override void WriteLine(string? value) { foreach (var w in _writers) w.WriteLine(value); }
|
||||
public override void Flush() { foreach (var w in _writers) w.Flush(); }
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="OpenMaui.Controls.Linux" Version="1.0.0-preview.*" />
|
||||
<ProjectReference Include="../../maui-linux/OpenMaui.Controls.Linux.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
21
WebViewDemo/App.cs
Normal file
21
WebViewDemo/App.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
// App.cs - Main Application with NavigationPage
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace WebViewDemo;
|
||||
|
||||
public class App : Application
|
||||
{
|
||||
public static NavigationPage? NavigationPage { get; private set; }
|
||||
|
||||
public App()
|
||||
{
|
||||
NavigationPage = new NavigationPage(new WebViewPage())
|
||||
{
|
||||
Title = "OpenMaui WebView Demo",
|
||||
BarBackgroundColor = Color.FromArgb("#5C6BC0"),
|
||||
BarTextColor = Colors.White
|
||||
};
|
||||
MainPage = NavigationPage;
|
||||
}
|
||||
}
|
||||
22
WebViewDemo/MauiProgram.cs
Normal file
22
WebViewDemo/MauiProgram.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
// MauiProgram.cs - MAUI app configuration
|
||||
|
||||
using Microsoft.Maui.Hosting;
|
||||
using Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
namespace WebViewDemo;
|
||||
|
||||
public static class MauiProgram
|
||||
{
|
||||
public static MauiApp CreateMauiApp()
|
||||
{
|
||||
var builder = MauiApp.CreateBuilder();
|
||||
|
||||
// Configure the app
|
||||
builder.UseMauiApp<App>();
|
||||
|
||||
// Add Linux platform support with all handlers
|
||||
builder.UseLinux();
|
||||
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
158
WebViewDemo/Pages/WebViewPage.xaml
Normal file
158
WebViewDemo/Pages/WebViewPage.xaml
Normal file
@@ -0,0 +1,158 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="WebViewDemo.WebViewPage"
|
||||
Title="WebView Demo"
|
||||
BackgroundColor="#F5F7FA">
|
||||
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<Color x:Key="PrimaryColor">#5C6BC0</Color>
|
||||
<Color x:Key="PrimaryDark">#3949AB</Color>
|
||||
<Color x:Key="AccentColor">#26A69A</Color>
|
||||
<Color x:Key="ButtonColor">#667EEA</Color>
|
||||
<Color x:Key="TextPrimary">#212121</Color>
|
||||
<Color x:Key="TextSecondary">#757575</Color>
|
||||
<Color x:Key="CardBackground">#FFFFFF</Color>
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<Grid RowDefinitions="Auto,Auto,Auto,*,Auto,Auto" Padding="16" RowSpacing="12">
|
||||
|
||||
<!-- Header -->
|
||||
<Label Grid.Row="0"
|
||||
Text="WebView Demo - WebKitGTK"
|
||||
FontSize="22"
|
||||
FontAttributes="Bold"
|
||||
TextColor="{StaticResource PrimaryColor}"
|
||||
HorizontalOptions="Center" />
|
||||
|
||||
<!-- Navigation Bar -->
|
||||
<Border Grid.Row="1"
|
||||
BackgroundColor="{StaticResource CardBackground}"
|
||||
StrokeThickness="0"
|
||||
Padding="12">
|
||||
<Border.StrokeShape>
|
||||
<RoundRectangle CornerRadius="8" />
|
||||
</Border.StrokeShape>
|
||||
|
||||
<HorizontalStackLayout Spacing="8" HorizontalOptions="Center">
|
||||
<Button x:Name="BackButton"
|
||||
Text="Back"
|
||||
WidthRequest="70"
|
||||
HeightRequest="36"
|
||||
FontSize="13"
|
||||
BackgroundColor="{StaticResource ButtonColor}"
|
||||
TextColor="White"
|
||||
Clicked="OnBackClicked" />
|
||||
<Button x:Name="ForwardButton"
|
||||
Text="Forward"
|
||||
WidthRequest="80"
|
||||
HeightRequest="36"
|
||||
FontSize="13"
|
||||
BackgroundColor="{StaticResource ButtonColor}"
|
||||
TextColor="White"
|
||||
Clicked="OnForwardClicked" />
|
||||
<Button x:Name="ReloadButton"
|
||||
Text="Reload"
|
||||
WidthRequest="70"
|
||||
HeightRequest="36"
|
||||
FontSize="13"
|
||||
BackgroundColor="{StaticResource ButtonColor}"
|
||||
TextColor="White"
|
||||
Clicked="OnReloadClicked" />
|
||||
</HorizontalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- URL Bar -->
|
||||
<Border Grid.Row="2"
|
||||
BackgroundColor="{StaticResource CardBackground}"
|
||||
StrokeThickness="0"
|
||||
Padding="12">
|
||||
<Border.StrokeShape>
|
||||
<RoundRectangle CornerRadius="8" />
|
||||
</Border.StrokeShape>
|
||||
|
||||
<Grid ColumnDefinitions="*,Auto" ColumnSpacing="8">
|
||||
<Entry x:Name="UrlEntry"
|
||||
Grid.Column="0"
|
||||
Placeholder="Enter URL..."
|
||||
Text="https://dotnet.microsoft.com"
|
||||
FontSize="14"
|
||||
VerticalOptions="Center"
|
||||
Completed="OnUrlSubmitted" />
|
||||
<Button x:Name="GoButton"
|
||||
Grid.Column="1"
|
||||
Text="Go"
|
||||
WidthRequest="60"
|
||||
HeightRequest="36"
|
||||
FontSize="13"
|
||||
BackgroundColor="{StaticResource AccentColor}"
|
||||
TextColor="White"
|
||||
Clicked="OnGoClicked" />
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!-- WebView -->
|
||||
<Border Grid.Row="3"
|
||||
BackgroundColor="{StaticResource CardBackground}"
|
||||
StrokeThickness="1"
|
||||
Stroke="#E0E0E0">
|
||||
<Border.StrokeShape>
|
||||
<RoundRectangle CornerRadius="8" />
|
||||
</Border.StrokeShape>
|
||||
|
||||
<WebView x:Name="MainWebView"
|
||||
VerticalOptions="Fill"
|
||||
HorizontalOptions="Fill"
|
||||
Navigating="OnNavigating"
|
||||
Navigated="OnNavigated" />
|
||||
</Border>
|
||||
|
||||
<!-- Action Buttons -->
|
||||
<Border Grid.Row="4"
|
||||
BackgroundColor="{StaticResource CardBackground}"
|
||||
StrokeThickness="0"
|
||||
Padding="12">
|
||||
<Border.StrokeShape>
|
||||
<RoundRectangle CornerRadius="8" />
|
||||
</Border.StrokeShape>
|
||||
|
||||
<HorizontalStackLayout Spacing="8" HorizontalOptions="Center">
|
||||
<Button x:Name="LoadHtmlButton"
|
||||
Text="Load HTML"
|
||||
WidthRequest="110"
|
||||
HeightRequest="36"
|
||||
FontSize="13"
|
||||
BackgroundColor="{StaticResource PrimaryColor}"
|
||||
TextColor="White"
|
||||
Clicked="OnLoadHtmlClicked" />
|
||||
<Button x:Name="EvalJsButton"
|
||||
Text="Run JS"
|
||||
WidthRequest="90"
|
||||
HeightRequest="36"
|
||||
FontSize="13"
|
||||
BackgroundColor="{StaticResource PrimaryColor}"
|
||||
TextColor="White"
|
||||
Clicked="OnEvalJsClicked" />
|
||||
</HorizontalStackLayout>
|
||||
</Border>
|
||||
|
||||
<!-- Status Bar -->
|
||||
<Border Grid.Row="5"
|
||||
BackgroundColor="{StaticResource PrimaryDark}"
|
||||
StrokeThickness="0"
|
||||
Padding="12,8">
|
||||
<Border.StrokeShape>
|
||||
<RoundRectangle CornerRadius="6" />
|
||||
</Border.StrokeShape>
|
||||
|
||||
<Label x:Name="StatusLabel"
|
||||
Text="Ready"
|
||||
FontSize="13"
|
||||
TextColor="White"
|
||||
HorizontalOptions="Center" />
|
||||
</Border>
|
||||
|
||||
</Grid>
|
||||
</ContentPage>
|
||||
178
WebViewDemo/Pages/WebViewPage.xaml.cs
Normal file
178
WebViewDemo/Pages/WebViewPage.xaml.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
// WebViewPage - Main page demonstrating WebView with WebKitGTK
|
||||
|
||||
using Microsoft.Maui.Controls;
|
||||
|
||||
namespace WebViewDemo;
|
||||
|
||||
public partial class WebViewPage : ContentPage
|
||||
{
|
||||
public WebViewPage()
|
||||
{
|
||||
Console.WriteLine("[WebViewPage] Constructor starting");
|
||||
InitializeComponent();
|
||||
|
||||
// Set initial URL
|
||||
MainWebView.Source = new UrlWebViewSource { Url = "https://dotnet.microsoft.com" };
|
||||
|
||||
Console.WriteLine("[WebViewPage] Constructor finished");
|
||||
}
|
||||
|
||||
private void OnBackClicked(object? sender, EventArgs e)
|
||||
{
|
||||
Console.WriteLine("[WebViewPage] Back button clicked");
|
||||
if (MainWebView.CanGoBack)
|
||||
{
|
||||
MainWebView.GoBack();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnForwardClicked(object? sender, EventArgs e)
|
||||
{
|
||||
Console.WriteLine("[WebViewPage] Forward button clicked");
|
||||
if (MainWebView.CanGoForward)
|
||||
{
|
||||
MainWebView.GoForward();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnReloadClicked(object? sender, EventArgs e)
|
||||
{
|
||||
Console.WriteLine("[WebViewPage] Reload button clicked");
|
||||
MainWebView.Reload();
|
||||
}
|
||||
|
||||
private void OnGoClicked(object? sender, EventArgs e)
|
||||
{
|
||||
Navigate();
|
||||
}
|
||||
|
||||
private void OnUrlSubmitted(object? sender, EventArgs e)
|
||||
{
|
||||
Navigate();
|
||||
}
|
||||
|
||||
private void Navigate()
|
||||
{
|
||||
var url = UrlEntry.Text?.Trim();
|
||||
if (string.IsNullOrEmpty(url))
|
||||
return;
|
||||
|
||||
// Add https:// if not present
|
||||
if (!url.StartsWith("http://") && !url.StartsWith("https://"))
|
||||
url = "https://" + url;
|
||||
|
||||
Console.WriteLine($"[WebViewPage] Navigating to: {url}");
|
||||
MainWebView.Source = new UrlWebViewSource { Url = url };
|
||||
UrlEntry.Text = url;
|
||||
}
|
||||
|
||||
private void OnNavigating(object? sender, WebNavigatingEventArgs e)
|
||||
{
|
||||
StatusLabel.Text = $"Loading: {e.Url}";
|
||||
Console.WriteLine($"[WebViewPage] Navigating to: {e.Url}");
|
||||
}
|
||||
|
||||
private void OnNavigated(object? sender, WebNavigatedEventArgs e)
|
||||
{
|
||||
StatusLabel.Text = e.Result == WebNavigationResult.Success
|
||||
? $"Loaded: {e.Url}"
|
||||
: $"Failed: {e.Result}";
|
||||
|
||||
UrlEntry.Text = e.Url;
|
||||
Console.WriteLine($"[WebViewPage] Navigated: {e.Result} - {e.Url}");
|
||||
}
|
||||
|
||||
private void OnLoadHtmlClicked(object? sender, EventArgs e)
|
||||
{
|
||||
Console.WriteLine("[WebViewPage] Load HTML button clicked");
|
||||
|
||||
var html = @"
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>OpenMaui WebView</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Arial, sans-serif;
|
||||
margin: 40px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
min-height: 100vh;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
p {
|
||||
font-size: 1.2em;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.feature-list {
|
||||
background: rgba(255,255,255,0.1);
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
li {
|
||||
margin: 10px 0;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
button {
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 15px 30px;
|
||||
font-size: 1.1em;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
margin-top: 20px;
|
||||
}
|
||||
button:hover {
|
||||
background: #45a049;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from OpenMaui Linux!</h1>
|
||||
<p>This HTML content is rendered by WebKitGTK inside your .NET MAUI application.</p>
|
||||
|
||||
<div class='feature-list'>
|
||||
<h2>WebView Features:</h2>
|
||||
<ul>
|
||||
<li>Full HTML5 support</li>
|
||||
<li>CSS3 animations and transitions</li>
|
||||
<li>JavaScript execution</li>
|
||||
<li>Navigation history (back/forward)</li>
|
||||
<li>WebGL and canvas support</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button onclick=""alert('Hello from JavaScript!')"">Click Me!</button>
|
||||
|
||||
<p style='margin-top: 30px; opacity: 0.8;'>
|
||||
Powered by WebKitGTK - the same engine used by GNOME Web (Epiphany)
|
||||
</p>
|
||||
</body>
|
||||
</html>";
|
||||
|
||||
MainWebView.Source = new HtmlWebViewSource { Html = html };
|
||||
StatusLabel.Text = "Loaded custom HTML";
|
||||
}
|
||||
|
||||
private async void OnEvalJsClicked(object? sender, EventArgs e)
|
||||
{
|
||||
Console.WriteLine("[WebViewPage] Run JS button clicked");
|
||||
|
||||
try
|
||||
{
|
||||
var result = await MainWebView.EvaluateJavaScriptAsync("document.title");
|
||||
StatusLabel.Text = $"JS Result: {result ?? "(null)"}";
|
||||
Console.WriteLine($"[WebViewPage] JS Eval result: {result}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
StatusLabel.Text = $"JS Error: {ex.Message}";
|
||||
Console.WriteLine($"[WebViewPage] JS Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,283 +1,67 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// Program.cs - Linux platform entry point
|
||||
|
||||
using Microsoft.Maui;
|
||||
using Microsoft.Maui.Controls;
|
||||
using Microsoft.Maui.Hosting;
|
||||
using Microsoft.Maui.Platform.Linux;
|
||||
using Microsoft.Maui.Platform.Linux.Hosting;
|
||||
|
||||
namespace WebViewDemo;
|
||||
|
||||
public static class MauiProgram
|
||||
class Program
|
||||
{
|
||||
public static MauiApp CreateMauiApp()
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var builder = MauiApp.CreateBuilder();
|
||||
builder.UseMauiApp<App>();
|
||||
builder.UseLinux();
|
||||
return builder.Build();
|
||||
}
|
||||
}
|
||||
// Redirect console output to a log file for debugging
|
||||
var logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "webviewdemo.log");
|
||||
using var logWriter = new StreamWriter(logPath, append: false) { AutoFlush = true };
|
||||
var multiWriter = new MultiTextWriter(Console.Out, logWriter);
|
||||
Console.SetOut(multiWriter);
|
||||
Console.SetError(multiWriter);
|
||||
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("[Program] Starting WebView Demo");
|
||||
|
||||
var app = MauiProgram.CreateMauiApp();
|
||||
LinuxApplication.Run(app, args);
|
||||
}
|
||||
}
|
||||
|
||||
public class App : Application
|
||||
{
|
||||
public App()
|
||||
{
|
||||
MainPage = new NavigationPage(new WebViewPage())
|
||||
// Global exception handler
|
||||
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
|
||||
{
|
||||
Title = "WebView Demo"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public class WebViewPage : ContentPage
|
||||
{
|
||||
private readonly WebView _webView;
|
||||
private readonly Entry _urlEntry;
|
||||
private readonly Label _statusLabel;
|
||||
|
||||
public WebViewPage()
|
||||
{
|
||||
Title = "WebView Demo";
|
||||
|
||||
_webView = new WebView
|
||||
{
|
||||
HeightRequest = 400,
|
||||
VerticalOptions = LayoutOptions.Fill,
|
||||
HorizontalOptions = LayoutOptions.Fill,
|
||||
Source = new UrlWebViewSource { Url = "https://dotnet.microsoft.com" }
|
||||
};
|
||||
|
||||
_webView.Navigating += OnNavigating;
|
||||
_webView.Navigated += OnNavigated;
|
||||
|
||||
_urlEntry = new Entry
|
||||
{
|
||||
Placeholder = "Enter URL...",
|
||||
Text = "https://dotnet.microsoft.com",
|
||||
HorizontalOptions = LayoutOptions.Fill
|
||||
};
|
||||
_urlEntry.Completed += OnUrlSubmitted;
|
||||
|
||||
_statusLabel = new Label
|
||||
{
|
||||
Text = "Ready",
|
||||
TextColor = Colors.Gray,
|
||||
FontSize = 12
|
||||
};
|
||||
|
||||
var goButton = new Button
|
||||
{
|
||||
Text = "Go",
|
||||
WidthRequest = 60
|
||||
};
|
||||
goButton.Clicked += (s, e) => Navigate();
|
||||
|
||||
var backButton = new Button
|
||||
{
|
||||
Text = "Back",
|
||||
WidthRequest = 60
|
||||
};
|
||||
backButton.Clicked += (s, e) => _webView.GoBack();
|
||||
|
||||
var forwardButton = new Button
|
||||
{
|
||||
Text = "Forward",
|
||||
WidthRequest = 80
|
||||
};
|
||||
forwardButton.Clicked += (s, e) => _webView.GoForward();
|
||||
|
||||
var reloadButton = new Button
|
||||
{
|
||||
Text = "Reload",
|
||||
WidthRequest = 70
|
||||
};
|
||||
reloadButton.Clicked += (s, e) => _webView.Reload();
|
||||
|
||||
var loadHtmlButton = new Button
|
||||
{
|
||||
Text = "Load HTML",
|
||||
WidthRequest = 100
|
||||
};
|
||||
loadHtmlButton.Clicked += OnLoadHtmlClicked;
|
||||
|
||||
var evalJsButton = new Button
|
||||
{
|
||||
Text = "Run JS",
|
||||
WidthRequest = 80
|
||||
};
|
||||
evalJsButton.Clicked += OnEvalJsClicked;
|
||||
|
||||
// Navigation bar
|
||||
var navBar = new HorizontalStackLayout
|
||||
{
|
||||
Spacing = 5,
|
||||
Children = { backButton, forwardButton, reloadButton }
|
||||
};
|
||||
|
||||
// URL bar
|
||||
var urlBar = new HorizontalStackLayout
|
||||
{
|
||||
Spacing = 5,
|
||||
Children = { _urlEntry, goButton }
|
||||
};
|
||||
|
||||
// Action buttons
|
||||
var actionBar = new HorizontalStackLayout
|
||||
{
|
||||
Spacing = 5,
|
||||
Children = { loadHtmlButton, evalJsButton }
|
||||
};
|
||||
|
||||
Content = new VerticalStackLayout
|
||||
{
|
||||
Padding = 10,
|
||||
Spacing = 10,
|
||||
Children =
|
||||
var ex = e.ExceptionObject as Exception;
|
||||
Console.WriteLine($"[FATAL] Unhandled exception: {ex?.GetType().Name}: {ex?.Message}");
|
||||
Console.WriteLine($"[FATAL] Stack trace: {ex?.StackTrace}");
|
||||
if (ex?.InnerException != null)
|
||||
{
|
||||
new Label { Text = "WebView Demo - WebKitGTK", FontSize = 20, FontAttributes = FontAttributes.Bold },
|
||||
navBar,
|
||||
urlBar,
|
||||
_webView,
|
||||
actionBar,
|
||||
_statusLabel
|
||||
Console.WriteLine($"[FATAL] Inner exception: {ex.InnerException.GetType().Name}: {ex.InnerException.Message}");
|
||||
Console.WriteLine($"[FATAL] Inner stack trace: {ex.InnerException.StackTrace}");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void Navigate()
|
||||
{
|
||||
var url = _urlEntry.Text?.Trim();
|
||||
if (string.IsNullOrEmpty(url))
|
||||
return;
|
||||
TaskScheduler.UnobservedTaskException += (sender, e) =>
|
||||
{
|
||||
Console.WriteLine($"[FATAL] Unobserved task exception: {e.Exception?.GetType().Name}: {e.Exception?.Message}");
|
||||
Console.WriteLine($"[FATAL] Stack trace: {e.Exception?.StackTrace}");
|
||||
e.SetObserved(); // Prevent crash
|
||||
};
|
||||
|
||||
// Add https:// if not present
|
||||
if (!url.StartsWith("http://") && !url.StartsWith("https://"))
|
||||
url = "https://" + url;
|
||||
Console.WriteLine($"[Program] Starting WebView Demo at {DateTime.Now}");
|
||||
Console.WriteLine($"[Program] Log file: {logPath}");
|
||||
|
||||
_webView.Source = new UrlWebViewSource { Url = url };
|
||||
_urlEntry.Text = url;
|
||||
}
|
||||
|
||||
private void OnUrlSubmitted(object? sender, EventArgs e)
|
||||
{
|
||||
Navigate();
|
||||
}
|
||||
|
||||
private void OnNavigating(object? sender, WebNavigatingEventArgs e)
|
||||
{
|
||||
_statusLabel.Text = $"Loading: {e.Url}";
|
||||
Console.WriteLine($"[WebViewPage] Navigating to: {e.Url}");
|
||||
}
|
||||
|
||||
private void OnNavigated(object? sender, WebNavigatedEventArgs e)
|
||||
{
|
||||
_statusLabel.Text = e.Result == WebNavigationResult.Success
|
||||
? $"Loaded: {e.Url}"
|
||||
: $"Failed: {e.Result}";
|
||||
|
||||
_urlEntry.Text = e.Url;
|
||||
Console.WriteLine($"[WebViewPage] Navigated: {e.Result} - {e.Url}");
|
||||
}
|
||||
|
||||
private void OnLoadHtmlClicked(object? sender, EventArgs e)
|
||||
{
|
||||
var html = @"
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>OpenMaui WebView</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Arial, sans-serif;
|
||||
margin: 40px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
min-height: 100vh;
|
||||
}
|
||||
h1 {
|
||||
font-size: 2.5em;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
p {
|
||||
font-size: 1.2em;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.feature-list {
|
||||
background: rgba(255,255,255,0.1);
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
li {
|
||||
margin: 10px 0;
|
||||
font-size: 1.1em;
|
||||
}
|
||||
button {
|
||||
background: #4CAF50;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 15px 30px;
|
||||
font-size: 1.1em;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
margin-top: 20px;
|
||||
}
|
||||
button:hover {
|
||||
background: #45a049;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello from OpenMaui Linux!</h1>
|
||||
<p>This HTML content is rendered by WebKitGTK inside your .NET MAUI application.</p>
|
||||
|
||||
<div class='feature-list'>
|
||||
<h2>WebView Features:</h2>
|
||||
<ul>
|
||||
<li>Full HTML5 support</li>
|
||||
<li>CSS3 animations and transitions</li>
|
||||
<li>JavaScript execution</li>
|
||||
<li>Navigation history (back/forward)</li>
|
||||
<li>WebGL and canvas support</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<button onclick=""alert('Hello from JavaScript!')"">Click Me!</button>
|
||||
|
||||
<p style='margin-top: 30px; opacity: 0.8;'>
|
||||
Powered by WebKitGTK - the same engine used by GNOME Web (Epiphany)
|
||||
</p>
|
||||
</body>
|
||||
</html>";
|
||||
|
||||
_webView.Source = new HtmlWebViewSource { Html = html };
|
||||
_statusLabel.Text = "Loaded custom HTML";
|
||||
}
|
||||
|
||||
private async void OnEvalJsClicked(object? sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await _webView.EvaluateJavaScriptAsync("document.title");
|
||||
_statusLabel.Text = $"JS Result: {result ?? "(null)"}";
|
||||
Console.WriteLine($"[WebViewPage] JS Eval result: {result}");
|
||||
// Create the MAUI app with all handlers registered
|
||||
var app = MauiProgram.CreateMauiApp();
|
||||
|
||||
// Run on Linux platform
|
||||
LinuxApplication.Run(app, args);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_statusLabel.Text = $"JS Error: {ex.Message}";
|
||||
Console.WriteLine($"[FATAL] Exception in Main: {ex.GetType().Name}: {ex.Message}");
|
||||
Console.WriteLine($"[FATAL] Stack trace: {ex.StackTrace}");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper to write to both console and file
|
||||
class MultiTextWriter : TextWriter
|
||||
{
|
||||
private readonly TextWriter[] _writers;
|
||||
public MultiTextWriter(params TextWriter[] writers) => _writers = writers;
|
||||
public override System.Text.Encoding Encoding => System.Text.Encoding.UTF8;
|
||||
public override void Write(char value) { foreach (var w in _writers) w.Write(value); }
|
||||
public override void WriteLine(string? value) { foreach (var w in _writers) w.WriteLine(value); }
|
||||
public override void Flush() { foreach (var w in _writers) w.Flush(); }
|
||||
}
|
||||
|
||||
@@ -5,14 +5,11 @@
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<RootNamespace>WebViewDemo</RootNamespace>
|
||||
<RuntimeIdentifier>linux-arm64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<PublishSingleFile>false</PublishSingleFile>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../../OpenMaui.Controls.Linux.csproj" />
|
||||
<ProjectReference Include="../../maui-linux/OpenMaui.Controls.Linux.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
Reference in New Issue
Block a user