Skip to content

Commit 6887f51

Browse files
authored
Update readme file.
1 parent 0e93fcb commit 6887f51

File tree

1 file changed

+182
-31
lines changed

1 file changed

+182
-31
lines changed

README.md

Lines changed: 182 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ A package that brings data-binding to your Unity project.
1212
- [Installation](#gear-installation)
1313
- [IL2CPP restriction](#il2cpp-restriction)
1414
- [Introduction](#ledger-introduction)
15+
- [ViewModel](#viewmodel)
16+
- [CanvasView\<TBindingContext\>](#canvasviewtbindingcontext)
17+
- [DocumentView\<TBindingContext\>](#documentviewtbindingcontext)
18+
- [Command & Command\<T\>](#command--commandt)
19+
- [AsyncCommand & AsyncCommand\<T\>](#asynccommand--asynccommandt)
20+
- [AsyncLazyCommand & AsyncLazyCommand\<T\>](#asynclazycommand--asynclazycommandt)
21+
- [PropertyValueConverter\<TSourceType, TTargetType\>](#propertyvalueconvertertsourcetype-ttargettype)
22+
- [ParameterValueConverter\<TTargetType\>](#parametervalueconverterttargettype)
1523
- [Quick start](#watch-quick-start)
1624
- [How To Use](#rocket-how-to-use)
1725
- [Data-binding](#data-binding)
@@ -197,7 +205,6 @@ The included types are:
197205
- [Command & Command\<T\>](#command--commandt)
198206
- [AsyncCommand & AsyncCommand\<T\>](#asynccommand--asynccommandt)
199207
- [AsyncLazyCommand & AsyncLazyCommand\<T\>](#asynclazycommand--asynclazycommandt)
200-
- [CommandWrapper](#commandwrapper)
201208
- [PropertyValueConverter\<TSourceType, TTargetType\>](#propertyvalueconvertertsourcetype-ttargettype)
202209
- [ParameterValueConverter\<TTargetType\>](#parametervalueconverterttargettype)
203210
- [ICommand & ICommand\<T\>](#command--commandt)
@@ -218,7 +225,7 @@ Key functionality:
218225
219226
#### Simple property
220227
221-
Here's an example of how to implement notification support to a custom property:
228+
Here's an example of how to implement notification support to a custom property.
222229
223230
```csharp
224231
public class CounterViewModel : ViewModel
@@ -237,7 +244,7 @@ The provided `Set<T>(ref T, T, string)` method checks the current value of the p
237244

238245
#### Wrapping a model
239246

240-
To inject notification support to models, that don't implement the `INotifyPropertyChanged` interface, `ViewModel` provides a dedicated `Set<TModel, T>(T, T, TModel, Action<TModel, T>, string)` method for this:
247+
To inject notification support to models, that don't implement the `INotifyPropertyChanged` interface, `ViewModel` provides a dedicated `Set<TModel, T>(T, T, TModel, Action<TModel, T>, string)` method for this.
241248

242249
```csharp
243250
public class UserViewModel : ViewModel
@@ -271,8 +278,6 @@ Key functionality:
271278
```csharp
272279
public class CounterView : CanvasView<CounterViewModel>
273280
{
274-
...
275-
276281
// Override the base viewmodel instance creation.
277282
// Required in case there is no default constructor for the viewmodel.
278283
protected override CounterViewModel GetBindingContext()
@@ -308,8 +313,6 @@ Key functionality:
308313
```csharp
309314
public class CounterView : DocumentView<CounterViewModel>
310315
{
311-
...
312-
313316
// Override the base viewmodel instance creation.
314317
// Required in case there is no default constructor for the viewmodel.
315318
protected override CounterViewModel GetBindingContext()
@@ -340,7 +343,7 @@ Key functionality:
340343
- Implement the `ICommand` & `ICommand<T>` interface, which exposes a `RaiseCanExecuteChanged` method to raise the `CanExecuteChanged` event
341344
- Expose constructor taking delegates like `Action` and `Action<T>`, which allow the wrapping of standard methods and lambda expressions
342345

343-
The following shows how to set up a simple command:
346+
The following shows how to set up a simple command.
344347

345348
```csharp
346349
using UnityMvvmToolkit.Core;
@@ -367,7 +370,7 @@ public class CounterViewModel : ViewModel
367370
}
368371
```
369372

370-
And the relative UI could then be (using UXML):
373+
And the relative UI could then be (using UXML).
371374

372375
```xml
373376
<ui:UXML xmlns:uitk="UnityMvvmToolkit.UITK.BindableUIElements" ...>
@@ -386,10 +389,10 @@ The `AsyncCommand` and `AsyncCommand<T>` are `ICommand` implementations that ext
386389

387390
Key functionality:
388391
- Extend the functionalities of the synchronous commands included in the package, with support for UniTask-returning delegates
389-
- Can wrap asynchronous functions with a `CancellationToken` parameter to support cancelation, and they implement a `DisableOnExecution` logic
392+
- Can wrap asynchronous functions with a `CancellationToken` parameter to support cancelation, and they expose a `DisableOnExecution` property, as well as a `Cancel` method
390393
- Implement the `IAsyncCommand` & `IAsyncCommand<T>` interfaces, which allows to replace a command with a custom implementation, if needed
391394

392-
Let's say we want to download an image from the web and display it as soon as it downloads:
395+
Let's say we want to download an image from the web and display it as soon as it downloads.
393396

394397
```csharp
395398
public class ImageViewerViewModel : ViewModel
@@ -418,7 +421,7 @@ public class ImageViewerViewModel : ViewModel
418421
}
419422
```
420423

421-
With the related UI code:
424+
With the related UI code.
422425

423426
```xml
424427
<ui:UXML xmlns:uitk="UnityMvvmToolkit.UITK.BindableUIElements" ...>
@@ -429,30 +432,51 @@ With the related UI code:
429432
</ui:UXML>
430433
```
431434

432-
To disable the `BindableButton` while an async operation is running, simply set the `DisableOnExecution` property of the `AsyncCommand` to `true`:
435+
To disable the `BindableButton` while an async operation is running, simply set the `DisableOnExecution` property of the `AsyncCommand` to `true`.
433436

434437
```csharp
435438
public class ImageViewerViewModel : ViewModel
436439
{
437-
...
438-
439440
public ImageViewerViewModel(IImageDownloader imageDownloader)
440441
{
441-
_imageDownloader = imageDownloader;
442-
DownloadImageCommand = new AsyncLazyCommand(DownloadImageAsync) { DisableOnExecution = true };
442+
...
443+
DownloadImageCommand = new AsyncCommand(DownloadImageAsync) { DisableOnExecution = true };
443444
}
445+
}
446+
```
447+
448+
If you want to create an async command that supports cancellation, use the `WithCancellation` extension method.
444449

445-
...
450+
```csharp
451+
public class MyViewModel : ViewModel
452+
{
453+
public MyViewModel()
454+
{
455+
MyAsyncCommand = new AsyncCommand(DoSomethingAsync).WithCancellation();
456+
CancelCommand = new Command(Cancel);
457+
}
458+
459+
public IAsyncCommand MyAsyncCommand { get; }
460+
public ICommand CancelCommand { get; }
461+
462+
private void Cancel()
463+
{
464+
// If the underlying command is not running, or
465+
// if it does not support cancellation, this method will perform no action.
466+
MyAsyncCommand.Cancel();
467+
}
446468
}
447469
```
448470

471+
If the command supports cancellation, previous invocations will automatically be canceled if a new one is started.
472+
449473
> **Note:** You need to import the [UniTask](https://github.com/Cysharp/UniTask) package in order to use async commands.
450474
451475
### AsyncLazyCommand & AsyncLazyCommand\<T\>
452476

453-
The `AsyncLazyCommand` and `AsyncLazyCommand<T>` are have the same functionality as the `AsyncCommand`'s, except they prevent the async operation from being run multiple times.
477+
The `AsyncLazyCommand` and `AsyncLazyCommand<T>` are have the same functionality as the `AsyncCommand`'s, except they prevent the same async command from being invoked concurrently multiple times.
454478

455-
Let's imagine a scenario similar to the one described in the `AsyncCommand` sample, but a user clicks the `Download Image` button several times during the async operation is running. In this case, `AsyncLazyCommand` will ignore all clicks until previous async operation has completed.
479+
Let's imagine a scenario similar to the one described in the `AsyncCommand` sample, but a user clicks the `Download Image` button several times while the async operation is running. In this case, `AsyncLazyCommand` will ignore all clicks until previous async operation has completed.
456480

457481
> **Note:** You need to import the [UniTask](https://github.com/Cysharp/UniTask) package in order to use async commands.
458482
@@ -462,11 +486,144 @@ Let's imagine a scenario similar to the one described in the `AsyncCommand` samp
462486

463487
### PropertyValueConverter\<TSourceType, TTargetType\>
464488

465-
...
489+
Property value converters provide a way to apply custom logic to a property binding.
490+
491+
Built-in property value converters:
492+
- IntToStrConverter
493+
- FloatToStrConverter
494+
495+
If you want to create your own property value converter, create a class that inherits the `PropertyValueConverter<TSourceType, TTargetType>` abstract class and then implement the `Convert` and `ConvertBack` methods.
496+
497+
```csharp
498+
public enum ThemeMode
499+
{
500+
Light = 0,
501+
Dark = 1
502+
}
503+
504+
public class ThemeModeToBoolConverter : PropertyValueConverter<ThemeMode, bool>
505+
{
506+
// From source to target.
507+
public override bool Convert(ThemeMode value)
508+
{
509+
return (int) value == 1;
510+
}
511+
512+
// From target to source.
513+
public override ThemeMode ConvertBack(bool value)
514+
{
515+
return (ThemeMode) (value ? 1 : 0);
516+
}
517+
}
518+
```
519+
Don't forget to register the `ThemeModeToBoolConverter` in the view.
520+
521+
```csharp
522+
public class MyView : DocumentView<MyViewModel>
523+
{
524+
protected override IValueConverter[] GetValueConverters()
525+
{
526+
return new IValueConverter[] { new ThemeModeToBoolConverter() };
527+
}
528+
}
529+
```
530+
531+
Then you can use the `ThemeModeToBoolConverter` as in the following example.
532+
533+
```xml
534+
<UXML>
535+
<MyBindableElement binding-value-path="ThemeMode, Converter={ThemeModeToBoolConverter}" />
536+
<!--or-->
537+
<MyBindableElement binding-value-path="ThemeMode, ThemeModeToBoolConverter" />
538+
</UXML>
539+
```
466540

467541
### ParameterValueConverter\<TTargetType\>
468542

469-
...
543+
Parameter value converters allow to convert a command parameter.
544+
545+
Built-in parameter value converters:
546+
- ParameterToStrConverter
547+
- ParameterToIntConverter
548+
- ParameterToFloatConverter
549+
550+
By default, the converter is not needed if your command has a `ReadOnlyMemory<char>` parameter type.
551+
552+
```csharp
553+
public class MyViewModel : ViewModel
554+
{
555+
public MyViewModel()
556+
{
557+
PrintParameterCommand = new Command<ReadOnlyMemory<char>>(PrintParameter);
558+
}
559+
560+
public ICommand<ReadOnlyMemory<char>> PrintParameterCommand { get; }
561+
562+
private void PrintParameter(ReadOnlyMemory<char> parameter)
563+
{
564+
Debug.Log(parameter);
565+
}
566+
}
567+
```
568+
569+
```xml
570+
<UXML>
571+
<BindableButton command="PrintParameterCommand, Parameter={MyParameter}" />
572+
<!--or-->
573+
<BindableButton command="PrintParameterCommand, MyParameter" />
574+
</UXML>
575+
```
576+
577+
If you want to create your own parameter value converter, create a class that inherits the `ParameterValueConverter<TTargetType>` abstract class and then implement the `Convert` method.
578+
579+
```csharp
580+
public class ParameterToIntConverter : ParameterValueConverter<int>
581+
{
582+
public override int Convert(ReadOnlyMemory<char> parameter)
583+
{
584+
return int.Parse(parameter.Span);
585+
}
586+
}
587+
```
588+
589+
Don't forget to register the `ParameterToIntConverter` in the view.
590+
591+
```csharp
592+
public class MyView : DocumentView<MyViewModel>
593+
{
594+
protected override IValueConverter[] GetValueConverters()
595+
{
596+
return new IValueConverter[] { new ParameterToIntConverter() };
597+
}
598+
}
599+
```
600+
601+
Then you can use the `ParameterToIntConverter` as in the following example.
602+
603+
```csharp
604+
public class MyViewModel : ViewModel
605+
{
606+
public MyViewModel()
607+
{
608+
PrintParameterCommand = new Command<int>(PrintParameter);
609+
}
610+
611+
public ICommand<int> PrintParameterCommand { get; }
612+
613+
private void PrintParameter(int parameter)
614+
{
615+
Debug.Log(parameter);
616+
}
617+
}
618+
```
619+
620+
```xml
621+
<UXML>
622+
<BindableButton command="PrintIntParameterCommand, Parameter={5}, Converter={ParameterToIntConverter}" />
623+
<!--or-->
624+
<BindableButton command="PrintIntParameterCommand, 5, ParameterToIntConverter" />
625+
</UXML>
626+
```
470627

471628
## :watch: Quick start
472629

@@ -662,23 +819,19 @@ public class CustomBindableElementsFactory : BindableElementsFactory
662819
```csharp
663820
public class ImageViewerViewModel : ViewModel
664821
{
665-
...
822+
private Texture2D _texture;
666823

667824
public Texture2D Image
668825
{
669826
get => _texture;
670827
private set => Set(ref _texture, value);
671828
}
672-
673-
...
674829
}
675830
```
676831

677832
```csharp
678833
public class ImageViewerView : DocumentView<ImageViewerViewModel>
679834
{
680-
...
681-
682835
protected override IBindableElementsFactory GetBindableElementsFactory()
683836
{
684837
return new CustomBindableElementsFactory();
@@ -688,9 +841,7 @@ public class ImageViewerView : DocumentView<ImageViewerViewModel>
688841

689842
```xml
690843
<UXML>
691-
...
692844
<BindableImage binding-image-path="Image" />
693-
...
694845
</UXML>
695846
```
696847

@@ -702,15 +853,15 @@ To enable [async commands](#asynccommand--asynccommandt) support, you need to ad
702853

703854
In addition to async commands **UnityMvvmToolkit** provides extensions to make [USS transition's](https://docs.unity3d.com/Manual/UIE-Transitions.html) awaitable.
704855

705-
For example, your `VisualElement` has the following transitions:
856+
For example, your `VisualElement` has the following transitions.
706857
```css
707858
.panel--animation {
708859
transition-property: opacity, padding-bottom;
709860
transition-duration: 65ms, 150ms;
710861
}
711862
```
712863

713-
You can `await` these transitions using several methods:
864+
You can `await` these transitions using several methods.
714865
```csharp
715866
public async UniTask DeactivatePanel()
716867
{

0 commit comments

Comments
 (0)