Skip to content

Commit

Permalink
adding more docs
Browse files Browse the repository at this point in the history
  • Loading branch information
MikeCodesDotNET committed Apr 24, 2023
1 parent eaef2f0 commit e71755d
Show file tree
Hide file tree
Showing 12 changed files with 724 additions and 3 deletions.
2 changes: 2 additions & 0 deletions .deployment
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[config]
SCM_DO_BUILD_DURING_DEPLOYMENT=true
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"appService.zipIgnorePattern": [
"node_modules{,/**}",
".vscode{,/**}"
],
"appService.defaultWebAppToDeploy": "/subscriptions/f706b20f-09d0-4fef-a2fc-629fa3973d06/resourceGroups/TestDocs/providers/Microsoft.Web/sites/avaloniauitestdocs",
"appService.deploySubpath": "."
}
1 change: 1 addition & 0 deletions docs/api/Avalonia-Animation/Animators.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

7 changes: 7 additions & 0 deletions docs/api/namespaces.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
sidebar_label: 'Namespaces!'
sidebar_position: 0
---

# Namespaces

80 changes: 80 additions & 0 deletions docs/guides/basics/accessing-the-ui-thread.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Accessing the UI thread

A `Dispatcher` provides services for managing work items on a specific thread. In Avalonia you will usually have only one `Dispatcher`, the one that handles the UI thread. Whenever you need to update the UI from a different thread than the UI thread, you need to access the UI thread via the running `Dispatcher`.

## Access the UI thread from a different thread

You can access the current UI thread via `Dispatcher.UIThread`. You can either use `Post` or `InvokeAsync`, if you want to run a job on the UI thread. Use `Post` when you just want to start a job, but you don't need to wait for the job to be finished and you don't need the result. If you need to wait for the result, then use `InvokeAsync` instead.

## The DispatcherPriority

The `DispatcherPriority` specifies at which priority the given job should be queued. For possible values please refer to the [API-Reference](http://reference.avaloniaui.net/api/Avalonia.Threading/DispatcherPriority/)

## Examples

In the below example we have a `TextBlock` which shows the result and a `Button` which is used to start our work.

Our view looks like this:

```markup
<StackPanel>
<TextBlock x:Name="TextBlock_Result" />
<Button Content="Run long running process" Click="Button_OnClick" />
</StackPanel>
```

The long running task looks like this:

```csharp
async Task LongRunningTask()
{
// Do some work
this.FindControl<TextBlock>("TextBlock_Result").Text = "I'm working ...";
await Task.Delay(2000);
this.FindControl<TextBlock>("TextBlock_Result").Text = "Done";
}
```

Finally we can run the long running task as shown below:

```csharp
private void Button_OnClick(object sender, RoutedEventArgs e)
{
// Start the job and return immediately
Dispatcher.UIThread.Post(() => LongRunningTask(), DispatcherPriority.Background);
}
```

if we want to get the result to work with it further, we need to change the long running task to return the result:

```csharp
async Task<string> LongRunningTask()
{
// Do some work
this.FindControl<TextBlock>("TextBlock_Result").Text = "I'm working ...";
await Task.Delay(2000);
this.FindControl<TextBlock>("TextBlock_Result").Text = "Done";

// return a result
return "Success";
}
```

We can use the result now:

```csharp
private async void Button_OnClick(object sender, RoutedEventArgs e)
{
// Run the job
var result = await Dispatcher.UIThread.InvokeAsync(LongRunningTask, DispatcherPriority.Background);

// Work with the result
Debug.WriteLine(result);
}
```

## Reference
[Dispatcher](http://reference.avaloniaui.net/api/Avalonia.Threading/Dispatcher/)

## Source Code
[Dispatcher.cs](https://github.com/AvaloniaUI/Avalonia/blob/master/src/Avalonia.Base/Threading/Dispatcher.cs)
173 changes: 173 additions & 0 deletions docs/guides/basics/code-behind.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Code-behind

[Window](https://docs.avaloniaui.net/docs/controls/window) and [UserControl](https://docs.avaloniaui.net/docs/controls/usercontrol) files also have an associated _code-behind_ file which usually has the extension `.xaml.cs` or `.axaml.cs` and may be displayed collapsed under the XAML file in your editor. Below you can see a `MainWindow.xaml` file along with its markdown file `MainWindow.xaml.cs` in Visual Studio:


The code-behind file by default defines a .NET class with the same name as your XAML file, e.g.

```csharp
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace AvaloniaApplication1
{
public class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
#if DEBUG
AttachDevTools();
#endif
}

private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
}

```

Note that this class definition corresponds closely to the XAML file:

```markup
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="AvaloniaApplication1.MainWindow">
</Window>
```

* The base class, `Window` is the root element of the XAML file
* The `x:Class` attribute references the fully-qualified name of the class defined in code-behind

If you make any changes to the base class, namespace, or name of the class, make sure to update both the code-behind and the XAML to ensure they match.

In addition, the class contains two more things of interest:

* It enables [DevTools](https://docs.avaloniaui.net/docs/getting-started/developer-tools) in debug mode
* It defines an `InitializeComponent` method which is used to load the XAML at runtime

### Locating Controls <a id="locating-controls"></a>

One of the main uses of the code-behind file is to manipulate controls using C\# code. To do this you'll usually first want to get a reference to a named control. This can be done using the `FindControl<T>` method:

```markup
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="AvaloniaApplication4.MainWindow">
<Button Name="myButton">Hello World</Button>
</Window>
```

```csharp
public class MainWindow : Window
{
private Button myButton;

public MainWindow()
{
InitializeComponent();
#if DEBUG
AttachDevTools();
#endif
}

private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
myButton = this.FindControl<Button>("myButton");
}
}
```

`FindControl` must be called after `AvaloniaXamlLoader.Load` has run because it's not until this point that the control will have been created.

The good news this step is not necessary if you're using [Avalonia.NameGenerator](https://github.com/AvaloniaUI/Avalonia.NameGenerator) package (added to the Avalonia templates by default), because it provides a code-generation step which creates this code for you.
In such case the code-behind class can be simplified to:

```csharp
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
```

Note the class is now declared as `partial`. That's because all the boilerplate code is now auto-generated by the Avalonia.NameGenerator at the second partial class which is not visible in the project.
For the given XAML, it will look like follows:

```csharp
// <auto-generated />
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;

namespace AvaloniaApplication1
{
partial class MainWindow
{
internal global::Avalonia.Controls.Button myButton;

/// <summary>
/// Wires up the controls and optionally loads XAML markup and attaches dev tools (if Avalonia.Diagnostics package is referenced).
/// </summary>
/// <param name="loadXaml">Should the XAML be loaded into the component.</param>
/// <param name="attachDevTools">Should the dev tools be attached.</param>
public void InitializeComponent(bool loadXaml = true, bool attachDevTools = true)
{
if (loadXaml)
{
AvaloniaXamlLoader.Load(this);
}

#if DEBUG
if (attachDevTools)
{
this.AttachDevTools();
}
#endif

myButton = this.FindControl<global::Avalonia.Controls.Button>("myButton");
}
}
}
```

The auto-generated `InitializeComponent` has arguments to optionally call the `AvaloniaXamlLoader.Load(this)` and `AttachDevTools`, so you don't need to call them yourself from your code-behind class anymore.
Never keep a method named `InitializeComponent` in your code-behind view class if you are using the generator with default settings. Read more at the [Avalonia.NameGenerator documentation](https://github.com/AvaloniaUI/Avalonia.NameGenerator#advanced-usage).

For the rest of the documentation, we'll assume you're either using Avalonia templates or added the Avalonia.NameGenerator package to your project manually.

### Handling Events <a id="handling-events"></a>

Another common use for the code-behind file is to define _event handlers_. Event handlers are defined as methods in the code-behind and referenced from XAML. For example to add a handler for a button click:

```markup
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="AvaloniaApplication4.MainWindow">
<Button Click="MyButton_Click">Hello World</Button>
</Window>
```

```csharp
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}

public void MyButton_Click(object sender, RoutedEventArgs e)
{
// Handle click here.
}
}
```

Loading

0 comments on commit e71755d

Please sign in to comment.