Skip to content

Commit 78fcfa0

Browse files
worldbeaterglennawatson
authored andcommitted
housekeeping: Improve code snippets in readme.md (#1825)
* housekeeping: Improve code snippets in readme.md * Add RxUI bindings example * Use OAPH instead of mutable collections * Reference OAPH and commands guides
1 parent 59327b0 commit 78fcfa0

File tree

1 file changed

+30
-29
lines changed

1 file changed

+30
-29
lines changed

README.md

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -66,68 +66,69 @@ Let’s say you have a text field, and whenever the user types something into it
6666
public interface ISearchViewModel
6767
{
6868
string SearchQuery { get; set; }
69-
ReactiveCommand<string, List<SearchResult>> Search { get; }
70-
ObservableCollection<SearchResult> SearchResults { get; }
69+
ReactiveCommand<string, IEnumerable<SearchResult>> Search { get; }
70+
IEnumerable<SearchResult> SearchResults { get; }
7171
}
7272
```
7373

7474
<h3>Define under what conditions a network request will be made</h3>
7575

76+
We're describing here, in a *declarative way*, the conditions in which the Search command is enabled. Now our Command IsEnabled is perfectly efficient, because we're only updating the UI in the scenario when it should change.
77+
7678
```csharp
77-
// Here we're describing here, in a *declarative way*, the conditions in
78-
// which the Search command is enabled. Now our Command IsEnabled is
79-
// perfectly efficient, because we're only updating the UI in the scenario
80-
// when it should change.
8179
var canSearch = this.WhenAnyValue(x => x.SearchQuery, query => !string.IsNullOrWhiteSpace(query));
8280
```
8381

8482
<h3>Make the network connection</h3>
8583

84+
ReactiveCommand has built-in support for background operations and guarantees that this block will only run exactly once at a time, and that the CanExecute will auto-disable and that property IsExecuting will be set accordingly whilst it is running.
85+
8686
```csharp
87-
// ReactiveCommand has built-in support for background operations and
88-
// guarantees that this block will only run exactly once at a time, and
89-
// that the CanExecute will auto-disable and that property IsExecuting will
90-
// be set accordingly whilst it is running.
9187
Search = ReactiveCommand.CreateFromTask(_ => searchService.Search(this.SearchQuery), canSearch);
9288
```
9389

9490
<h3>Update the user interface</h3>
9591

96-
```csharp
97-
// ReactiveCommands are themselves IObservables, whose value are the results
98-
// from the async method, guaranteed to arrive on the UI thread. We're going
99-
// to take the list of search results that the background operation loaded,
100-
// and them into our SearchResults.
101-
Search.Subscribe(results =>
102-
{
103-
SearchResults.Clear();
104-
SearchResults.AddRange(results);
105-
});
92+
ReactiveCommands are themselves `IObservables`, whose values are the results from the async method, guaranteed to arrive on the UI thread. We're going to take the list of search results that the background operation loaded, and turn them into our SearchResults property declared as [`ObservableAsPropertyHelper<T>`](https://reactiveui.net/docs/handbook/oaph/#example).
10693

94+
```csharp
95+
_searchResults = Search.ToProperty(this, x => x.SearchResults);
10796
```
10897

10998
<h3>Handling failures</h3>
11099

100+
Any exception thrown from the [`ReactiveCommand.CreateFromTask`](https://reactiveui.net/docs/handbook/commands/) gets piped to the `ThrownExceptions` Observable. Subscribing to this allows you to handle errors on the UI thread.
101+
111102
```csharp
112-
// ThrownExceptions is any exception thrown from the CreateAsyncTask piped
113-
// to this Observable. Subscribing to this allows you to handle errors on
114-
// the UI thread.
115-
Search.ThrownExceptions.Subscribe(error =>
116-
{
117-
UserError.Throw("Potential Network Connectivity Error", error);
118-
});
103+
Search.ThrownExceptions.Subscribe(error => { /* Handle exceptions. */ });
119104
```
120105

121106
<h3>Throttling network requests and automatic search execution behaviour</h3>
122107

108+
Whenever the Search query changes, we're going to wait for one second of "dead airtime", then automatically invoke the subscribe command.
109+
123110
```csharp
124-
// Whenever the Search query changes, we're going to wait for one second
125-
// of "dead airtime", then automatically invoke the subscribe command.
126111
this.WhenAnyValue(x => x.SearchQuery)
127112
.Throttle(TimeSpan.FromSeconds(1), RxApp.MainThreadScheduler)
128113
.InvokeCommand(Search);
129114
```
130115

116+
<h3>Binding our ViewModel to the platform-specific UI</h3>
117+
118+
ReactiveUI fully supports XAML markup bindings, but we have more to offer. [ReactiveUI Bindings](https://reactiveui.net/docs/handbook/data-binding/) work on **all platforms**, including Xamarin Native and Windows Forms, and operate the same. Those bindings are strongly typed, and renaming a ViewModel property, or a control in the UI layout without updating the binding, the build will fail.
119+
120+
```csharp
121+
this.WhenActivated(cleanup =>
122+
{
123+
this.Bind(ViewModel, x => x.SearchQuery, x => x.TextBox)
124+
.DisposeWith(cleanup);
125+
this.OneWayBind(ViewModel, x => x.SearchResults, x => x.ListView)
126+
.DisposeWith(cleanup);
127+
this.BindCommand(ViewModel, x => x.Search, x => x.Button)
128+
.DisposeWith(cleanup);
129+
});
130+
```
131+
131132
<h2>Support</h2>
132133

133134
If you have a question, please see if any discussions in our [GitHub issues](github.com/reactiveui/ReactiveUI/issues) or [Stack Overflow](https://stackoverflow.com/questions/tagged/reactiveui) have already answered it.

0 commit comments

Comments
 (0)