Skip to content

Commit

Permalink
docs: MVUX Feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
nickrandolph committed Jul 4, 2023
1 parent c858f37 commit 5863b12
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 19 deletions.
6 changes: 2 additions & 4 deletions doc/Overview/Mvux/FeedView.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ uid: Overview.Mvux.FeedView

# The `FeedView` control

The `FeedView` control is the heart of MVUX on the View side and is one of the main way to consume Feeds and States within an application. The `FeedView` uses different visual states to control what is displayed on the screen depending on the state of the underlying feed, or state.
The `FeedView` control is one of the main ways to consume Feeds and States within an application. The `FeedView` uses different visual states to control what is displayed on the screen depending on the state of the underlying feed, or state.

## How to use the `FeedView` control

Expand Down Expand Up @@ -55,9 +55,7 @@ In the above example, [`Data`](#data) is a property of the `FeedViewState` insta

### State

The `State` property provides a `FeedViewState` which exposes the current state of the `FeedView`'s underlying data Feed wrapped in its metadata in an accessible way for the View to represent easily using the built-in or the customized templates accordingly.

It's unlikely that you'll need to access the `State` property directly since the `FeedViewState` is automatically set as the `DataContext` of the various templates.
The `State` property returns a `FeedViewState` which exposes the current state of the `FeedView`'s underlying data Feed. It's unlikely that you'll need to access the `State` property directly since the `FeedViewState` is automatically set as the `DataContext` of the various templates.

#### The `FeedViewState` object

Expand Down
4 changes: 2 additions & 2 deletions doc/Overview/Mvux/Feeds.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Feeds include additional metadata that indicates whether the operation is still

Feeds are typically used to request data from services and expose it in a stateless manner so that the resulting data can be displayed by the View.

Feeds are stateless and do not provide support for reacting upon changes the user makes to the data on the View, the data can only be reloaded and refreshed upon request which is when the underlying task or Async-Enumerable will be invoked and the data refreshed. In other words, a feed is a read-only representation of the data received from the server.
Feeds are stateless and does not provide support for reacting to changes the user makes to the data on the View. The data can only be reloaded and refreshed upon request which is when the underlying task or Async-Enumerable will be invoked and the data refreshed. In other words, a feed is a read-only representation of the data received from the server.

In contrast to feeds, [states](xref:Overview.Mvux.States) (`IState` or `IListState`), as the name suggests, are stateful and keep track of the latest value, as updates are applied.

Expand Down Expand Up @@ -115,7 +115,7 @@ public void SetUp()

#### Awaiting feeds

Feeds are directly awaitable, so to get the data currently held in the feed, this is useful when you want to use the current value in a command, etc. You can await it in the following manner:
Feeds are directly awaitable, so to get the data currently held in the feed, the feed needs to be awaited. This is useful when you want to use the current value in a method, for example:

```csharp
public IFeed<CurrentCount> CurrentCount => ...
Expand Down
9 changes: 2 additions & 7 deletions doc/Overview/Mvux/ListStates.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,6 @@ public IListFeed<string> FavoritesFeed => ...
public IListState<string> FavoritesState => ListState.FromFeed(this, FavoritesFeed);
```

## Others

There's also the `ListState.Create` method which allows you to manually build the list-state with Messages.
You can learn about manual creation of Messages [here](xref:Overview.Reactive.State#create).

## Operators

In the following examples, we'll refer to `MyStrings` which is an `IListState<string>`, to demonstrate how to use the various operators `IListState<T>` provides to update its state with modified data.
Expand Down Expand Up @@ -117,7 +112,7 @@ public async ValueTask TrimAll(CancellationToken ct = default)
}
```

Another overload is `UpdateAsync`, which allows you to apply an update on select item criteria, using a predicate that is checked before updating an individual update, and if an item qualifies, uses the `updater` argument, which in this case is a `Func<T, T>` which applies to an individual item:
Another overload is `UpdateAsync`, which allows you to apply an update on items that match a criteria. The `match` predicate is checked for each item.It the item matches the criteria, the updater is invoked which returns a new instance of the item with the update applied:

```csharp
public async ValueTask TrimLongNames(CancellationToken ct = default)
Expand All @@ -141,7 +136,7 @@ The `RemoveAllAsync` method uses a predicate to determine which items are to be

### ForEachAsync

This operator can be called from an `IListState<T>` to execute an asynchronous action on all items currently in the list-state each time its data is changed (values are either added or removed):
This operator can be called from an `IListState<T>` to execute an asynchronous action then the data changes. The action is invoked once for the entire set of data, rather than for individual items:

```csharp
await MyStrings.ForEachAsync(async(list, ct) => await PerformAction(items, ct));
Expand Down
8 changes: 4 additions & 4 deletions doc/Overview/Mvux/Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ MVUX is an extension to the MVU design pattern, and leverages code generation in

### Model

The **Model** in MVUX is similar in many ways to the viewmodel in MVVM in that it defines the properties that will be available for data binding and methods that include any business logic. In MVUX this is referred to as the Model, highlighting that it is immutable by design.
The **Model** in MVUX is similar in many ways to the viewmodel in MVVM. The **Model** defines the properties that will be available for data binding and methods that include any business logic. In MVUX this is referred to as the **Model**, highlighting that it is immutable by design.

For our weather app, `WeatherModel` is the **Model**, and defines a property named `CurrentWeather`.

Expand All @@ -68,7 +68,7 @@ The **View** is the UI, which can be written in XAML, C#, or a combination of th
</Page>
```

If you're familiar with MVVM, the above XAML would look familiar, as it's the same XAML you would write if you had a viewmodel that exposed a `CurrentWeather` property that returns an entity that has a `Temperature` property.
This XAML data binds the `Text` property on the `TextBlock` to the `CurrentWeather.Temperature` property on the `DataContext` of the page. In other words, the `CurrentWeather` property is retrieved from the `DataContext`. If the resulting object is not null, the `Temperature` property is retrieved and used to set the `Text` property on the `TextBlock`.

What's unique to MVUX is the additional information that `IFeed` exposes, such as when data is being loaded and whether there was an error loading the data. For this, we can leverage the MVUX `FeedView` control.

Expand All @@ -89,11 +89,11 @@ What's unique to MVUX is the additional information that `IFeed` exposes, such a
</Page>
```

The `FeedView` control is designed to work with an `IFeed`, and has different visual states that align with the different states that an `IFeed` can be in (e.g. loading, refreshing, error, etc.). The above XAML defines the `ValueTemplate`, which is required in order to display the `Data` from the `IFeed`. Other templates include `ProgressTemplate`, `ErrorTemplate` and `NoneTemplate`, which can be defined in order to control what's displayed depending on the state of the `IFeed`.
The `FeedView` control is designed to work with an `IFeed`, and has visual states that align with the states that an `IFeed` can be in (e.g. loading, refreshing, error, etc.). The above XAML defines the `ValueTemplate`, which is required in order to display the `Data` from the `IFeed`. Other templates include `ProgressTemplate`, `ErrorTemplate` and `NoneTemplate`, which can be defined in order to control what's displayed depending on the state of the `IFeed`.

### Update

An **Update** is any action that will result in a change to the **Model**. Whilst an **Update** is often triggered via an interaction by the user with the **View**, such as editing text or clicking a button, an **Update** can also be triggered from a background process (for example a data sync operation or perhaps a notification triggered by a hardware sensor, such as a GPS).
An **Update** is any action that will result in a change to the **Model**. An **Update** is often triggered via an interaction by the user with the **View**, such as editing text or clicking a button. However, an **Update** can also be triggered from a background process (for example a data sync operation or perhaps a notification triggered by a hardware sensor, such as a GPS).

In the weather example, if we wanted to refresh the current weather data, a `Refresh` method can be added to the `WeatherModel`.

Expand Down
4 changes: 2 additions & 2 deletions doc/Overview/Mvux/States.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public async ValueTask IncrementSlider(CancellationToken ct = default)
}
```

The `updater` parameter of the `Update` method accepts a `Func<T, T>`, where the input parameter provides the current value of the State when called, and the return parameter is the one to be returned and applied as the new value of the State, in our case we use the `incrementValue` [local function](https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/local-functions) to increment `currentValue` by one (or return `1` if the value exceeds `100`).
The `updater` parameter of the `Update` method accepts a `Func<T, T>`. The input parameter provides the current value of the State when called. The return value is the new value that will be applied as the new value of the State, in our case we use the `incrementValue` [local function](https://learn.microsoft.com/dotnet/csharp/programming-guide/classes-and-structs/local-functions) to increment `currentValue` by one (or return `1` if the value exceeds `100`).

#### Set

Expand All @@ -177,7 +177,7 @@ public async ValueTask SetSliderMiddle(CancellationToken ct = default)

The `ForEachAsync` enables executing a callback each time the value of the `IState<T>` is updated.

This extension-method takes a single parameter which is a async callback that takes two parameters, the first one is `T?` where `T` is what the `IState<T>` is of, and the second is a `CancellationToken`. It returns a `ValueTask`.
This extension-method takes a single parameter which is a async callback that takes two parameters. The first parameter is of type `T?`, where `T` is type of the `IState`, and represents the new value of the state. The second parameter is a `CancellationToken` which can be used to cancel a long running action.

For example:

Expand Down

0 comments on commit 5863b12

Please sign in to comment.