Skip to content

Commit

Permalink
add some documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
tomlm committed Dec 18, 2024
1 parent ee3e836 commit 126edb3
Show file tree
Hide file tree
Showing 12 changed files with 516 additions and 8 deletions.
57 changes: 57 additions & 0 deletions docs/Application.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Consolonia Application
The ConosoloniaApplication is just like the normal Avalonia Application, but with some extra features.

The main task for an application is to
* Define the initial window
* Defining the application resources (like styles, themes, etc.)

## Creating the initial window
The MainWindow is the main window of the application which derives from `Window` class.
You can do it like a traditional avalonia app:
```csharp
public class App : ConsoloniaApplication
{
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MyMainWindow();
}
base.OnFrameworkInitializationCompleted();
}
}
```
or you can use the ConsoloniaApplication<T> class to make it easier:

```csharp
public class MyApplication : ConsoloniaApplication<MyMainWindow>
{
public MyApplication()
{
// Initialize the application
}
}
```


## Define application resources
The application has a global ResourceDictionary and Styles collection which allows you to set global resources for your application.
It is very common to define the theme in the Application.

```csharp
class MyApp : ConsoloniaApplication<MyMainWindow>
{
public MyApp()
{
Styles.Add(new MaterialTheme());
}
}
```

# References
* [Overview](/docs)
* [Quick Start](/docs/QuickStart.md)
* [Application](/docs/Application.md)
* [Dialogs](/docs/Dialogs.md)
* [Blazor](/docs/Blazor.md)

105 changes: 105 additions & 0 deletions docs/Blazor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Consolonia.Blazor
The Consolonia.Blazor package gives you the ability to use .razor and Blazor bindings to define your views.
* Use [⚡ Blazor](https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor) syntax for [Avalonia](https://avaloniaui.net/) apps
* 😎 Simpler syntax than XAML
* 🪄 IntelliSense support
* Get free [🔥 Hot Reload](https://devblogs.microsoft.com/dotnet/introducing-net-hot-reload/) support on-top
* See https://github.com/Epictek/Avalonia-Blazor-Bindings

# Enabling Consolonia.Blazor

1. Add nuget reference to Consolonia.Blazor
To enable Blazor in your project you need to add the following to your project file.
```xaml
<ItemGroup>
<PackageReference Include="Consolonia.Blazor" />
</ItemGroup>
```

2. Replace `.UseConsolonia()` with `.UseConsoloniaBlazor()` in your AppBuilder
```csharp
public static AppBuilder BuildAvaloniaApp()
{
return AppBuilder.Configure<App>()
.UseConsoloniaBlazor() // <-- instead of .UseConsolonia()
.UseAutoDetectedConsole()
.LogToException();
}
```

## Define a view in .razor

```razor
@page "/"
@inject INavigation navigation
@inject IClassicDesktopStyleApplicationLifetime lifetime
@namespace Example.Blazor.Components
<Window Title="Blazor Bindings for Consolonia" Topmost="true">
<StackPanel Orientation="Orientation.Vertical" VerticalAlignment="VerticalAlignment.Center">
@if (showCounter)
{
<TextBlock HorizontalAlignment="HorizontalAlignment.Center">Counter: @CounterText</TextBlock>
}
<StackPanel Orientation="Orientation.Vertical" HorizontalAlignment="HorizontalAlignment.Center" Margin="@Thickness.Parse("4")">
<Button OnClick="@OnIncrement">Increment counter support</Button>
<Button OnClick="@OnToggleCounter">@ToggleText</Button>
<Button OnClick="@OnMessageBox">Message Box</Button>
<Button OnClick="@OnGotoSubPage">Go to SubPage</Button>
<Button OnClick="@OnExit">Exit</Button>
</StackPanel>
</StackPanel>
</Window>
@code {
int counter = 0;
bool showCounter = true;
string CounterText => counter switch
{
0 => "Not clicked",
1 => $"Clicked 1 time",
_ => $"Clicked {counter} times"
};
string ToggleText => showCounter ? "Hide Counter" : "Show Counter";
void OnIncrement()
=> counter++;
void OnToggleCounter()
=> showCounter = !showCounter;
void OnGotoSubPage()
=> navigation.PushAsync<SubPage>();
async void OnMessageBox(RoutedEventArgs args)
{
await new MessageBox()
.ShowDialogAsync((AC.Control)args.Source!, "Hello, Blazor!", "Blazor Bindings for Consolonia");
}
void OnExit()
=> lifetime.Shutdown();
}
```

Things to note:
* Method binding to code behind
* Conditional layout of elements
* Full intellisense for renaming going to code behind autocomplete etc.
* injection of **INavigation** so you can push and pop views off of the nav stack
* injection of **IClassicDesktopStyleApplicationLifetime** so you can access Args and shutdown the app.
* HOT RELOAD. simple save the file and your view gets rebuilt and rerendered!

![blazor](https://github.com/user-attachments/assets/ae1ba484-b3a9-46c6-8c1b-99026e7f924c)

# References
* [Overview](/docs)
* [Quick Start](/docs/QuickStart.md)
* [Application](/docs/Application.md)
* [Dialogs](/docs/Dialogs.md)
* [Blazor](/docs/Blazor.md)


113 changes: 113 additions & 0 deletions docs/Dialogs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Dialogs
Console apps don't have model dialogs, so Consolonia implements them as a custom control.

## Define a Dialog
To define a dialog you create a element which derives from **DialogWindow**

```xaml
<controls:DialogWindow xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Consolonia.Core.Controls;assembly=Consolonia.Core"
HorizontalAlignment="Center"
VerticalAlignment="Center"
x:Class="Consolonia.Gallery.Gallery.GalleryViews.SomeDialogWindow">
<Panel>
<TextBlock Text="Hello World" />
<Button Content="DoSomething"
Name="DoSomethingButton"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Click="DoSomethingButton_Clicked" />
</Panel>
</controls:DialogWindow>
```


## Show a Dialog
To show a dialog you create an instance of the dialog and call the ShowDialog method.
```csharp
var dialog = new SomeDialogWindow();
var result = async dialog.ShowDialogAsync<MyResult>();
```

## Close a Dialog
To close a dialog you call the Close method, optionally passing a result.
```csharp
Close(new MyResult());
```

## Dialog Result
The result of the dialog is returned from the ShowDialogAsync method. The result will be of type ResultT and will be the result of the object returned when the .Close() method is called.

# MessageBox
Consolonia implements a DialogWindow called MessageBox class which makes it simple to show simple message boxes and get input from the user.

## Show a MessageBox
To show a message box you instantiate a MessageBox object and call the ShowDialogAsync method. The kind of buttons shown will depend on the mode that is passed in.

```csharp
var mb = new MessageBox
{
Mode = Mode.YesNoCancel,
Title = "Yes/No/Cancel Message box"
};
var result = await MessageBox.ShowDialogAsync("Hello World");
```

|DialogMode | Description |
|-----------|-------------|
| **Ok** | Shows an OK button |
| **OkCancel** | Shows an OK and Cancel button |
| **YesNo** | Shows a Yes and No button |
| **YesNoCancel** | Shows a Yes, No and Cancel button |

The result of the message box is of type MessageBoxResult and will be the result of the button clicked.

|DialogBoxResult | Description |
|-----------|-------------|
| **Ok** | OK button was clicked |
| **Cancel** | Cancel button was clicked |
| **Yes** | Yes button was clicked |
| **No** | No button was clicked |


# IStorage in Consolonia
The Avalonia `IStorage` interface provides a way to interact with various storage mechanisms. In Consolonia it implements them using a DialogWindow providing character based way of letting the user interact with the file system.

![Storage](images/storage.png)

## Getting access to the IStorage interface
The storage interface is defined on the application lifetime, which is available via `Application.Current.ApplicationLifetime`

```csharp
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime)
{
IStorageProvider storageProvider = lifetime.MainWindow.StorageProvider;
if (storageProvider.CanOpen)
{
var files = await storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{
Title = title,
AllowMultiple = allowMultiple,
SuggestedStartLocation = new SystemStorageFolder(new DirectoryInfo(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments))),
FileTypeFilter = new List<FilePickerFileType>
{
new("All files") { Patterns = ["*"] },
new("Text") { Patterns = ["*.txt"] },
new("Comma Delimited Files") { Patterns = ["*.csv"] },
new("PDF") { Patterns = ["*.pdf"] }
}
});
// files is the selected files.
...
```

> See (Avalonia Storage Options)[https://docs.avaloniaui.net/docs/concepts/services/storage-provider/storage-item] for more details on the options available.
# References
* [Overview](/docs)
* [Quick Start](/docs/QuickStart.md)
* [Application](/docs/Application.md)
* [Dialogs](/docs/Dialogs.md)
* [Blazor](/docs/Blazor.md)

15 changes: 15 additions & 0 deletions docs/Docs.projitems
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects Condition="'$(MSBuildVersion)' == '' Or '$(MSBuildVersion)' &lt; '16.0'">$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<SharedGUID>939942df-366b-4edc-8145-825c3e7ce8ba</SharedGUID>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<Import_RootNamespace>Docs</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<None Include="**/*.md" />
<None Include="**/*.png" />
</ItemGroup>
</Project>
13 changes: 13 additions & 0 deletions docs/Docs.shproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>939942df-366b-4edc-8145-825c3e7ce8ba</ProjectGuid>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
<PropertyGroup />
<Import Project="Docs.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
</Project>
Loading

0 comments on commit 126edb3

Please sign in to comment.