Skip to content

Commit fd3a5f0

Browse files
authored
Update readme file.
1 parent 1cad44b commit fd3a5f0

File tree

1 file changed

+172
-19
lines changed

1 file changed

+172
-19
lines changed

README.md

Lines changed: 172 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,8 @@ Key functionality:
214214
- Provides a base implementation for `INotifyPropertyChanged`, exposing the `PropertyChanged` events
215215
- Provides a series of `Set` methods that can be used to easily set property values from types inheriting from `ViewModel`, and to automatically raise the appropriate events
216216
217+
> **Note:** In case your viewmodel doesn't have a parameterless constructor, you need to override the `GetBindingContext` method on the view.
218+
217219
#### Simple property
218220
219221
Here's an example of how to implement notification support to a custom property:
@@ -257,8 +259,78 @@ public class UserViewModel : ViewModel
257259

258260
### CanvasView\<TBindingContext\>
259261

262+
The `CanvasView<TBindingContext>` is a base class for `uGUI` view's.
263+
264+
Key functionality:
265+
- Provides a base implementation for `Canvas` based view
266+
- Automatically searches for bindable UI elements on the `Canvas`
267+
- Allows to override the base viewmodel instance creation
268+
- Allows to define 'property' & 'parameter' value converters
269+
- Allows to define custom UI elements
270+
271+
```csharp
272+
public class CounterView : CanvasView<CounterViewModel>
273+
{
274+
...
275+
276+
// Override the base viewmodel instance creation.
277+
// Required in case there is no default constructor for the viewmodel.
278+
protected override CounterViewModel GetBindingContext()
279+
{
280+
return _appContext.Resolve<CounterViewModel>();
281+
}
282+
283+
// Define 'property' & 'parameter' value converters.
284+
protected override IValueConverter[] GetValueConverters()
285+
{
286+
return _appContext.Resolve<IValueConverter[]>();
287+
}
288+
289+
// Define custom UI elements.
290+
protected override IBindableElementsFactory GetBindableElementsFactory()
291+
{
292+
return _appContext.Resolve<IBindableElementsFactory>();
293+
}
294+
}
295+
```
296+
260297
### DocumentView\<TBindingContext\>
261298

299+
The `DocumentView<TBindingContext>` is a base class for `UI Toolkit` view's.
300+
301+
Key functionality:
302+
- Provides a base implementation for `UI Document` based view
303+
- Automatically searches for bindable UI elements on the `UI Document`
304+
- Allows to override the base viewmodel instance creation
305+
- Allows to define 'property' & 'parameter' value converters
306+
- Allows to define custom UI elements
307+
308+
```csharp
309+
public class CounterView : DocumentView<CounterViewModel>
310+
{
311+
...
312+
313+
// Override the base viewmodel instance creation.
314+
// Required in case there is no default constructor for the viewmodel.
315+
protected override CounterViewModel GetBindingContext()
316+
{
317+
return _appContext.Resolve<CounterViewModel>();
318+
}
319+
320+
// Define 'property' & 'parameter' value converters.
321+
protected override IValueConverter[] GetValueConverters()
322+
{
323+
return _appContext.Resolve<IValueConverter[]>();
324+
}
325+
326+
// Define custom UI elements.
327+
protected override IBindableElementsFactory GetBindableElementsFactory()
328+
{
329+
return _appContext.Resolve<IBindableElementFactory>();
330+
}
331+
}
332+
```
333+
262334
### Command & Command\<T\>
263335

264336
The `Command` and `Command<T>` are `ICommand` implementations that can expose a method or delegate to the view. These types act as a way to bind commands between the viewmodel and UI elements.
@@ -298,9 +370,9 @@ public class CounterViewModel : ViewModel
298370
And the relative UI could then be (using UXML):
299371

300372
```xml
301-
<ui:UXML ...>
302-
<UnityMvvmToolkit.UITK.BindableUIElements.BindableLabel binding-text-path="Count" />
303-
<UnityMvvmToolkit.UITK.BindableUIElements.BindableButton command="IncrementCommand" />
373+
<ui:UXML xmlns:uitk="UnityMvvmToolkit.UITK.BindableUIElements" ...>
374+
<uitk:BindableLabel binding-text-path="Count" />
375+
<uitk:BindableButton command="IncrementCommand" />
304376
</ui:UXML>
305377
```
306378

@@ -349,11 +421,11 @@ public class ImageViewerViewModel : ViewModel
349421
With the related UI code:
350422

351423
```xml
352-
<ui:UXML ...>
353-
<BindableUIElements.BindableImage binding-image-path="Image" style="width: 256px; height: 256px;" />
354-
<UnityMvvmToolkit.UITK.BindableUIElements.BindableButton command="DownloadImageCommand">
424+
<ui:UXML xmlns:uitk="UnityMvvmToolkit.UITK.BindableUIElements" ...>
425+
<BindableImage binding-image-path="Image" />
426+
<uitk:BindableButton command="DownloadImageCommand">
355427
<ui:Label text="Download Image" />
356-
</UnityMvvmToolkit.UITK.BindableUIElements.BindableButton>
428+
</uitk:BindableButton>
357429
</ui:UXML>
358430
```
359431

@@ -386,10 +458,16 @@ Let's imagine a scenario similar to the one described in the `AsyncCommand` samp
386458
387459
### CommandWrapper
388460

461+
...
462+
389463
### PropertyValueConverter\<TSourceType, TTargetType\>
390464

465+
...
466+
391467
### ParameterValueConverter\<TTargetType\>
392468

469+
...
470+
393471
## :watch: Quick start
394472

395473
Once the `UnityMVVMToolkit` is installed, create a class `MyFirstViewModel` and inherit from the `ViewModel`.
@@ -429,8 +507,8 @@ public class MyFirstDocumentView : DocumentView<MyFirstViewModel>
429507
Create a file `MyFirstView.uxml`, add a `BindableLabel` control and set the `binding-text-path` to `Text`.
430508

431509
```xml
432-
<ui:UXML ...>
433-
<UnityMvvmToolkit.UITK.BindableUIElements.BindableLabel binding-text-path="Text" />
510+
<ui:UXML xmlns:uitk="UnityMvvmToolkit.UITK.BindableUIElements" ...>
511+
<uitk:BindableLabel binding-text-path="Text" />
434512
</ui:UXML>
435513
```
436514

@@ -477,6 +555,37 @@ Add a `Text - TextMeshPro` UI element to the canvas, add the `BindableLabel` com
477555

478556
### Data-binding
479557

558+
The package contains a set of standard bindable UI elements out of the box.
559+
560+
The included UI elements are:
561+
- [BindableLabel](bindablelabel)
562+
- [BindableTextField](bindabletextfield)
563+
- [BindableButton](bindablebutton)
564+
- [BindableListView](bindablelistview)
565+
- [BindableScrollView](bindablescrollview)
566+
567+
> **Note:** The `ListView` & `ScrollView` are provided for `UI Toolkit` only.
568+
569+
#### BindableLabel
570+
571+
`OneWay` binding
572+
573+
#### BindableTextField
574+
575+
`TwoWay` binding
576+
577+
#### BindableButton
578+
579+
...
580+
581+
#### BindableListView
582+
583+
...
584+
585+
#### BindableScrollView
586+
587+
...
588+
480589
### Create custom control
481590

482591
```csharp
@@ -536,15 +645,15 @@ public class BindableImageWrapper : BindablePropertyElement
536645
```
537646

538647
```csharp
539-
public class CustomBindableElementsWrapper : BindableElementsWrapper
648+
public class CustomBindableElementsFactory : BindableElementsFactory
540649
{
541-
public override IBindableElement Wrap(IBindableUIElement bindableUiElement, IObjectProvider objectProvider)
650+
public override IBindableElement Create(IBindableUIElement bindableUiElement, IObjectProvider objectProvider)
542651
{
543652
return bindableUiElement switch
544653
{
545654
BindableImage bindableImage => new BindableImageWrapper(bindableImage, objectProvider),
546655

547-
_ => base.Wrap(bindableUiElement, objectProvider)
656+
_ => base.Create(bindableUiElement, objectProvider)
548657
};
549658
}
550659
}
@@ -570,9 +679,9 @@ public class ImageViewerView : DocumentView<ImageViewerViewModel>
570679
{
571680
...
572681

573-
protected override IBindableElementsWrapper GetBindableElementsWrapper()
682+
protected override IBindableElementsFactory GetBindableElementsFactory()
574683
{
575-
return new CustomBindableElementsWrapper();
684+
return new CustomBindableElementsFactory();
576685
}
577686
}
578687
```
@@ -589,14 +698,58 @@ public class ImageViewerView : DocumentView<ImageViewerViewModel>
589698

590699
### UniTask
591700

592-
#### Async commands
701+
To enable [async commands](#asynccommand--asynccommandt) support, you need to add the [UniTask](https://github.com/Cysharp/UniTask) package to your project.
593702

594-
...
595-
<!--For IAsyncCommand support, it is required to import com.demigiant.unitask from OpenUPM or-->
703+
In addition to async commands **UnityMvvmToolkit** provides extensions to make [USS transition's](https://docs.unity3d.com/Manual/UIE-Transitions.html) awaitable.
596704

597-
#### Transition async extensions
705+
For example, your `VisualElement` has the following transitions:
706+
```css
707+
.panel--animation {
708+
transition-property: opacity, padding-bottom;
709+
transition-duration: 65ms, 150ms;
710+
}
711+
```
598712

599-
...
713+
You can `await` these transitions using several methods:
714+
```csharp
715+
public async UniTask DeactivatePanel()
716+
{
717+
try
718+
{
719+
panel.style.opacity = 0;
720+
panel.style.paddingBottom = 0;
721+
722+
// Await for the 'opacity' || 'paddingBottom' to end or cancel.
723+
await panel.WaitForAnyTransitionEnd();
724+
725+
// Await for the 'opacity' & 'paddingBottom' to end or cancel.
726+
await panel.WaitForAllTransitionsEnd();
727+
728+
// Await 150ms.
729+
await panel.WaitForLongestTransitionEnd();
730+
731+
// Await 65ms.
732+
await panel.WaitForTransitionEnd(0);
733+
734+
// Await for the 'paddingBottom' to end or cancel.
735+
await panel.WaitForTransitionEnd(new StylePropertyName("padding-bottom"));
736+
737+
// Await for the 'paddingBottom' to end or cancel.
738+
// Uses ReadOnlySpan to match property names to avoid memory allocation.
739+
await panel.WaitForTransitionEnd(nameof(panel.style.paddingBottom));
740+
741+
// Await for the 'opacity' || 'paddingBottom' to end or cancel.
742+
// You can write your own transition predicates, just implement a 'ITransitionPredicate' interface.
743+
await panel.WaitForTransitionEnd(new TransitionAnyPredicate());
744+
}
745+
finally
746+
{
747+
panel.visible = false;
748+
}
749+
}
750+
```
751+
752+
> **Note:** All transition extensions have a `timeoutMs` parameter (default value is `2500ms`).
600753
601754
## :chart_with_upwards_trend: Benchmarks
602755

0 commit comments

Comments
 (0)