-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
299 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Duck Typing in CSharp | ||
|
||
Currently only `GetEnumerator` and `Deconstruct` supports duck typing. | ||
`Dispose` is just not available since you the compiler won't be able to know which one to pick if there's duplication. | ||
|
||
```cs | ||
using System.Collections; | ||
|
||
using var foo = new Foo(); // [!code error] | ||
foreach (var _ in new Foo()) ; | ||
var (a, b) = new Foo(); | ||
|
||
class Foo; | ||
|
||
static class FooExtension | ||
{ | ||
public static void Dispose(this Foo self) => Console.WriteLine("Disposing Foo"); | ||
public static IEnumerator GetEnumerator(this Foo _) | ||
{ | ||
for (int i = 0; i < 100; i++) | ||
yield return i; | ||
} | ||
public static void Deconstruct(this Foo self, out object? a, out object? b) => a = b = null; | ||
} | ||
``` |
51 changes: 51 additions & 0 deletions
51
docs/document/Avalonia/docs/2. Styling/AXAML/Adding New Style.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# Adding New Style | ||
|
||
## With dotnet cli | ||
|
||
```sh | ||
dotnet new avalonia.styles -o Styles -n NewStyle | ||
``` | ||
|
||
## Default Template | ||
|
||
Style template ships with a portion for previewer where you can add testing controls to see whether those styles works properly. | ||
|
||
```xml | ||
<Styles xmlns="https://github.com/avaloniaui" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> | ||
<Design.PreviewWith> <!-- [!code highlight] --> | ||
<Border Padding="20"> <!-- [!code highlight] --> | ||
<!-- Add Controls for Previewer Here --> <!-- [!code highlight] --> | ||
</Border> <!-- [!code highlight] --> | ||
</Design.PreviewWith> <!-- [!code highlight] --> | ||
|
||
<!-- Add Styles Here --> | ||
</Styles> | ||
``` | ||
|
||
## Define a Style | ||
|
||
A style starts with a `Selector` which is the rule of target matching, for figuring out which control should have those contained styling. | ||
Contained styling is some key-value pair on properties. | ||
|
||
> [!NOTE] | ||
> See [selector syntax]() | ||
```xml | ||
<Styles xmlns="https://github.com/avaloniaui" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> | ||
<Design.PreviewWith> <!-- [!code highlight] --> | ||
<Border Padding="20"> <!-- [!code highlight] --> | ||
<!-- Add Controls for Previewer Here --> <!-- [!code highlight] --> | ||
</Border> <!-- [!code highlight] --> | ||
</Design.PreviewWith> <!-- [!code highlight] --> | ||
|
||
<!-- Add Styles Here --> | ||
<Style Selector="TextBlock.h1"> <!-- [!code ++] --> | ||
<Setter Property="FontWeight" Value="Bold" /> <!-- [!code ++] --> | ||
<Setter Property="FontSize" Value="15" /> <!-- [!code ++] --> | ||
<Setter Property="Margin" Value="5" /> <!-- [!code ++] --> | ||
</Style> <!-- [!code ++] --> | ||
|
||
</Styles> | ||
``` |
19 changes: 19 additions & 0 deletions
19
docs/document/Avalonia/docs/2. Styling/AXAML/Importing Styles.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
## Importing Styles | ||
|
||
```xml | ||
<UserControl xmlns="https://github.com/avaloniaui" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
xmlns:control="using:AvaloniaApplication" | ||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" | ||
x:Class="AvaloniaApplication.MyUserControl"> | ||
|
||
<UserControl.Styles> <!-- [!code highlight] --> | ||
<StyleInclude Source="MyStyles.axaml"></StyleInclude> <!-- [!code highlight] --> | ||
</UserControl.Styles> <!-- [!code highlight] --> | ||
|
||
<TextBlock Text="Hello from template" TextAlignment="Center" Width="200" Height="20"/> | ||
|
||
</UserControl> | ||
``` |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
136 changes: 135 additions & 1 deletion
136
docs/document/Avalonia/docs/MVVM Essentials/4. Trigger a Command.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,137 @@ | ||
# Trigger a Command | ||
|
||
## RelayCommand | ||
`CommunityToolkit.Mvvm` uses `RelayCommand` to generate a field and property to represents the command for certain method. | ||
|
||
## Code Emission | ||
|
||
```cs | ||
[RelayCommand] | ||
private void RemoveItem(ToDoItemViewModel item) | ||
{ | ||
ToDoItems.Remove(item); | ||
} | ||
``` | ||
|
||
Generated part as following: | ||
|
||
- A field of type `RelayCommand`(not the `RelayCommandAttribute`) | ||
- A property for the generated field typed as `IRelayCommand`. | ||
|
||
```cs | ||
/// <summary>The backing field for <see cref="RemoveItemCommand"/>.</summary> | ||
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator", "8.3.0.0")] | ||
private global::CommunityToolkit.Mvvm.Input.RelayCommand<global::ToDoList.ViewModels.ToDoItemViewModel>? removeItemCommand; // [!code highlight] | ||
/// <summary>Gets an <see cref="global::CommunityToolkit.Mvvm.Input.IRelayCommand{T}"/> instance wrapping <see cref="RemoveItem"/>.</summary> | ||
[global::System.CodeDom.Compiler.GeneratedCode("CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator", "8.3.0.0")] | ||
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage] | ||
public global::CommunityToolkit.Mvvm.Input.IRelayCommand<global::ToDoList.ViewModels.ToDoItemViewModel> RemoveItemCommand => removeItemCommand ??= new global::CommunityToolkit.Mvvm.Input.RelayCommand<global::ToDoList.ViewModels.ToDoItemViewModel>(new global::System.Action<global::ToDoList.ViewModels.ToDoItemViewModel>(RemoveItem)); // [!code highlight] | ||
``` | ||
|
||
## Behind the `RelayCommand` | ||
|
||
To understand how `RelayCommand` works, we should go back to the story of `ICommand` first. | ||
|
||
`ICommand` is a builtin interface in .NET, has three parts to describe the command pattern: | ||
- `Execute`: A real action for the command. | ||
- `CanExecute`: Telling whether the command can be executed now. | ||
- `CanExecuteChanged`: Informing when `CanExecute` evaluation changed. | ||
|
||
```cs | ||
public interface ICommand | ||
{ | ||
/// <summary>Occurs when changes occur that affect whether or not the command should execute.</summary> | ||
event EventHandler? CanExecuteChanged; | ||
|
||
/// <summary>Defines the method that determines whether the command can execute in its current state.</summary> | ||
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param> | ||
/// <returns> | ||
/// <see langword="true" /> if this command can be executed; otherwise, <see langword="false" />.</returns> | ||
bool CanExecute(object? parameter); | ||
|
||
/// <summary>Defines the method to be called when the command is invoked.</summary> | ||
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to <see langword="null" />.</param> | ||
void Execute(object? parameter); | ||
} | ||
``` | ||
|
||
`IRelayCommand` in `CommunityToolkit` simply extends the `ICommand` with a new notify method. | ||
We do need a real implementation of how we inform on `CanExecuteChanged`, this is generally missing in .NET builtin event-driven interfaces. | ||
|
||
```cs | ||
public interface IRelayCommand : ICommand | ||
{ | ||
/// <summary> | ||
/// Notifies that the <see cref="ICommand.CanExecute"/> property has changed. // [!code highlight] | ||
/// </summary> | ||
void NotifyCanExecuteChanged(); | ||
} | ||
``` | ||
|
||
> [!NOTE] | ||
> `IRelayCommand` and `RelayCommand` have generic versions and async versions. | ||
The type of generated field is `RelayCommand` which implements the `IRelayCommand`, this is essentially a base wrapper for the logic behind. | ||
|
||
```cs | ||
public sealed partial class RelayCommand : IRelayCommand | ||
{ | ||
/// <summary> | ||
/// The <see cref="Action"/> to invoke when <see cref="Execute"/> is used. | ||
/// </summary> | ||
private readonly Action execute; | ||
|
||
/// <summary> | ||
/// The optional action to invoke when <see cref="CanExecute"/> is used. | ||
/// </summary> | ||
private readonly Func<bool>? canExecute; | ||
|
||
/// <inheritdoc/> | ||
public event EventHandler? CanExecuteChanged; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="RelayCommand"/> class that can always execute. | ||
/// </summary> | ||
/// <param name="execute">The execution logic.</param> | ||
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="execute"/> is <see langword="null"/>.</exception> | ||
public RelayCommand(Action execute) | ||
{ | ||
ArgumentNullException.ThrowIfNull(execute); | ||
|
||
this.execute = execute; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="RelayCommand"/> class. | ||
/// </summary> | ||
/// <param name="execute">The execution logic.</param> | ||
/// <param name="canExecute">The execution status logic.</param> | ||
/// <exception cref="System.ArgumentNullException">Thrown if <paramref name="execute"/> or <paramref name="canExecute"/> are <see langword="null"/>.</exception> | ||
public RelayCommand(Action execute, Func<bool> canExecute) | ||
{ | ||
ArgumentNullException.ThrowIfNull(execute); | ||
ArgumentNullException.ThrowIfNull(canExecute); | ||
|
||
this.execute = execute; | ||
this.canExecute = canExecute; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public void NotifyCanExecuteChanged() | ||
{ | ||
CanExecuteChanged?.Invoke(this, EventArgs.Empty); | ||
} | ||
|
||
/// <inheritdoc/> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public bool CanExecute(object? parameter) | ||
{ | ||
return this.canExecute?.Invoke() != false; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public void Execute(object? parameter) | ||
{ | ||
this.execute(); | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
docs/document/Powershell/docs/Powershell as a Language/Function.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Function | ||
|
||
## Parameter | ||
|
||
There's no positional parameters, it's a table-like definition, can be specified with any order. | ||
Parameters are wrapped inside a function block with `param(...)` | ||
|
||
```ps1 | ||
function Foo { | ||
param ( | ||
[string]$foo | ||
) | ||
} | ||
``` | ||
|
||
### Default Parameter | ||
|
||
```ps1 | ||
function Foo { | ||
param ( | ||
[string]$foo = "foo" | ||
) | ||
} | ||
``` | ||
|
||
### Flags | ||
|
||
Defining flags that represents a toggle needs a special type called `switch`. | ||
`switch` has the same nature of `bool`, but `bool` parameter requires explicit assignment when the function being called. | ||
While `switch` will remain `$false` when unspecified. | ||
|
||
```ps1 | ||
function Foo { | ||
param ( | ||
[switch]$foo | ||
[bool]$bar | ||
) | ||
} | ||
# this is why we should use `switch` instead. | ||
Foo -foo -bar $true # [!code highlight] | ||
``` | ||
|
||
### Required Parameter | ||
|
||
All parameters are optional by default. Use `[Parameter(Mandatory=$true)]` to mark it as required. | ||
|
||
```ps1 | ||
param ( | ||
[Parameter(Mandatory=$true)] | ||
[string]$RequiredName | ||
) | ||
``` | ||
|
||
## Lifetime | ||
|
||
- Function should be define before it was called. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,5 +8,6 @@ | |
"vitePressExtensions": [ | ||
".md" | ||
] | ||
} | ||
}, | ||
"esModuleInterop": true | ||
} |