Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactiveUI - Should I use {Binding } or this.Bind(...)?

When using ReactiveUI, one can set the bindings in xaml ...

<TextBox x:Name="SomeProperty" Text="{Binding SomeProperty}" />

or in code behind

this.Bind(ViewModel, vm.SomeProperty, v => v.SomeProperty.Text);

There seem to be certain circumstances (such as binding to child objects in a ListBox) where using the .xaml option seems the only way to go

eg

<ListView>
    <ListView.ItemTemplate>
        <DataTemplate DataType="ListViewItem">
            <TextBox Text="{Binding ChildViewModelProperty}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Am I wrong to use {Binding } or can i mix and match .xaml and code behind as i see fit?!

like image 757
3-14159265358979323846264 Avatar asked Nov 21 '22 09:11

3-14159265358979323846264


1 Answers

I think you might get away (almost) without using XAML bindings, at the additional cost of writing more code. I'll use Anaïs Betts' XamarinEvolve2014 demo as an example.

First, you need to define a ViewModel for an item in your list (similar to LoginTeamTileViewModel):

public class TileViewModel : ReactiveObject
{
    string name;
    public string Name {
        get { return name; }
        set { this.RaiseAndSetIfChanged(ref name, value); }
    }
}

Then, you need to expose the collection of these classes in your ViewModel - for example as a ReactiveList:

public class ViewModel : ReactiveObject
{
    public ReactiveList<TileViewModel> Tiles { get; private set; }
}

You can use ReactiveDerivedCollection to create these ViewModels from your model.

Next, you create a simple View for the TileViewModel, similar to this one from Evolve example.

Finally, you should use created view as a data template in your list view, like in the example. Note that it still uses {Binding}, but only for the ViewModel property and not for separate fields, which seems cleaner. (Sadly, I haven't written any WPF in a while, so I will not be able to quickly write any example here - edit is welcome!).

In your code behind, you should bind your collection to the ItemsSource of the ListView, like here:

this.OneWayBind(ViewModel, vm => vm.Tiles, v => v.ListView.ItemsSource);

Hope this helps!

like image 63
pmbanka Avatar answered Dec 18 '22 17:12

pmbanka