Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

add some documentation #217

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>();
```
Comment on lines +29 to +31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix inconsistency in code example

The variable name in the example is inconsistent with the text. The ShowDialogAsync call has a typo.

-var result = async dialog.ShowDialogAsync<MyResult>();
+var result = await dialog.ShowDialogAsync<MyResult>();
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
var dialog = new SomeDialogWindow();
var result = async dialog.ShowDialogAsync<MyResult>();
```
var dialog = new SomeDialogWindow();
var result = await 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
Loading