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

2

7

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?!

Danita answered 12/4, 2016 at 11:5 Comment(2)
I would always prefer this.Bind syntax since it's much more powerful and compile time checked, and resort to {Binding} when it is necessary (like in your example).Makkah
BTW, ReactiveUI can use a separate UserControl for your DataTemplate. See this answer: #25466760Makkah
S
5

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!

Sena answered 13/4, 2016 at 15:25 Comment(1)
Plz use XAML binding as much as possible. Especially when those are simple. For more advanced scenario use codebehind in LAST resort. XAML IS compile-time checked if you set the x:DataType property. I fully agree with Monty's answer below.Muckrake
D
-5

No you are not wrong to use Binding.... If you want to 'Master' WPF\XAML then stick to MVVM pattern (Binding), and I mean stick to it.... if you 'mix and match .xaml and code behind' you will end up with unmaintainable, unmanageable spaghetti code....

Sounds like you already have a grasp of 'Binding' and your challenge should be to code a WPF application with absolutely NO code-behind except for what was created by Visual Studio...

Personally, I refuse to work on WPF applications that do not follow the MVVM pattern, it tells me that the original developer was not bothered about writing code that another developer (OR even themselves) could work.....

you might find this link useful...

https://rachel53461.wordpress.com/category/mvvm/

ionoy

Any code placed in the Window\UserControl *.cs file breaks the MVVM pattern with possibly the exception of a Custom Control where you would use Dependencyproperties to expose properties in the property editor (at design-time)...

For example, you should use RelayCommand (or DelegateCommand) that implements ICommand instead of event handlers. That is to say, never simply double-click on a button to create the event stub in the *.cs file of a Window (is not MVVM), create a Command in the ViewModel, which should be a separate file (not the Window.cs file coz that inherits from Window which is wrong as is a UserControl which inherits UserControl). Your ViewModel needs to implement InotifyPropertyChanged OR inherit a ViewModelBase that implements InotifyPropertyChanged, then you should use the Command and CommandParameter of the button to Bind too and call\pass objects back to the ViewModel, that's MVVM

you might find this useful...

http://www.c-sharpcorner.com/UploadFile/raj1979/simple-mvvm-pattern-in-wpf/

Deuterogamy answered 12/4, 2016 at 12:28 Comment(11)
Please learn what ReactiveUI is before answering the question about ReactiveUI. In no way it breaks MVVM pattern.Makkah
Please read my answer properly before commenting... I didn't say that ReactiveUI breaks MVVM pattern....Deuterogamy
But you are implying that having code in code-behind breaks MVVM, which is simply not true, especially when we are talking about bindings.Makkah
Placing code in the code-behind file and Binding are two different things. I have updated my answer with more info.....Deuterogamy
Believe me, I know what MVVM is. But you have to consider OP's question, he is asking about creating binding either in XAML or in code-behind. Both are viable options, both don't break MVVM. Please, consider taking a look at what ReactiveUI is before answering a question about ReactiveUI (repeating myself here).Makkah
'binding either in XAML or in code-behind'... No is the simple answer, Bindings only in XAML... you should never reference any UI object in the Code-behind, it defeats MVVM pattern by 'nailing' the UI to the code.Deuterogamy
Not at all... The whole point of MVVM is to separate the UI from the Code, your code should STILL compile if you remove\comment out the XAML. If you start referencing UI controls from the ViewModel (or code-behind) then your code will not compile and that's not MVVM. Also, 'Code-behind' suggest using the class that is created with the Window\UserControl... there should be no code in that class except the constructor... not even the DC should be initialised there really... Any code should go into a ViewModel and nothing in that should directly reference a UI Control...Deuterogamy
Any code placed in the Window\UserControl *.cs file breaks the MVVM pattern - this is simply not true. For example, RxUI-style bindings do not break MVVM.Sena
@Monty I guess you should look how MVVM works in different languages. Keeping WPF views code-behind-free (which is a goal with zero benefits) is completely different from the idea of separating presentation logic from all other logic (which is why MVVM exists in the first place). You can even use no XAML at all for WPF and still write perfectly valid MVVM code.Gamester
@Makkah as what I know about ReactiveUI, binding in code behind is able ONLY when the elements (controls) are named, right? And that's a bit bothersome compared to binding in XAML (sometimes we still need to name elements, but almost the time we don't have to). Also binding in internal Templates should be done in XAML and not easily be done in code behind (which requires a lot of code). So actually if going the way of ReactiveUI, we always need the standard binding approach.Pollinize
@hopeless yes, you need to name your controls for binding. It's a bit bothersome, I agree. But in return, you get statically checked bindings that won't fail you at runtime. As for templates, you can always create a UserControl and put it in the DataTemplate. No need to complicate things.Makkah

© 2022 - 2024 — McMap. All rights reserved.