Question

I'm very new to C# and WPF in general, having come from a LAMP web application background. I've tried following a couple tutorials on the subject but they have left me stumped.

https://rachel53461.wordpress.com/2011/05/08/simplemvvmexample/ http://www.codeproject.com/Articles/165368/WPF-MVVM-Quick-Start-Tutorial

In the first tutorial the application opens with a simple interface. A TextBox and two buttons. When you update the ProductId TextBox, going from 0 to 1, the "Get Product" button becomes active. When you click on the "Get Product" button the DataTemplate's contents appear. I can't see where these things are actually happening. What causes the button to become active? What causes the form to appear?

Hopefully you guys and gals can dumb it down for me =)

Was it helpful?

Solution

The buttons become activated or deactivated since they're bound to an ICommand. ICommand includes a CanExecute property, which determines whether the button is active or not.

I can't see where these things are actually happening.

The command uses delegates:

 _getProductCommand = new RelayCommand(
                param => GetProduct(),
                param => ProductId > 0
            );

The second delegate causes the command to be activated (CanExecute becomes true) when ProductId > 0 (the delegate returns true).

When you click the button, the command's Execute method fires, and performs the actions.

As for the window starting up in the first place, look at the section titled "Starting the Sample" - there's code in app.xaml.cs which is used to display the Window at first.

OTHER TIPS

In that specific example you can see:

<TextBox Grid.Row="0" Grid.Column="1" Text="{Binding ProductId}" />

The TextBox uses data binding to bind its Text property to the ProductId on the current data context (which is an instance of the view model).

When you type text in the TextBox, its value will be automatically updated on the ProductId property on the view model.

The command checks the value of the ProductId is greater than 0 to determine if the Button is enabled.

You can see the Button's command is set to the GetProductCommand:

<Button ... Command="{Binding Path=GetProductCommand}" ... />

The GetProductCommand uses the expression ProductId > 0 as its CanExecute predicate:

_getProductCommand = new RelayCommand(
              param => GetProduct(),
              param => ProductId > 0
);

WPF will execute this lambda expression ProductId > 0 whose result will determine if the Button is enabled. When the button is enabled and clicked, the first lambda expression will be executed - GetProduct().

Having said all this, you really should be using an MVVM framework, and these frameworks have other mechanisms for invoking methods on your view model which get past some of the limitations of commanding.

Essentially the Idea behind MVVM or Model, View, ViewModel is to remove that code behind and separate out the layers of the application so they can be worked on independently. The interaction between your GUI or View and Viewmodel or codebehind isn't happening like you probably think it is. A lot of people get confused on how the viewmodel actually interacts with the gui or view. I was a winforms dev with the code behind file in which you could easily see event handlers in the code behind and follow the code logically. In your MainWindow Code behind your setting the data context of the XAML gui to the view model like so.

public partial class MainWindow : Window
{
    #region Members
    SongViewModel _viewModel;
    int _count = 0;
    #endregion

    public MainWindow()
    {
        InitializeComponent();

        //  We have declared the view model instance declaratively in the xaml.
        //  Get the reference to it here, so we can use it in the button click event.
        _viewModel = (SongViewModel)base.DataContext;
    }

    private void ButtonUpdateArtist_Click(object sender, RoutedEventArgs e)
    {
        ++_count;
        _viewModel.ArtistName = string.Format("Elvis ({0})", _count);
    }
}    

Then the {Binding Path=Property} is wiring up your properties of your _viewModel to the XAML Elements. Adding the RaisePropertyChanged is what is notifying the gui that the value of that property has changed.

public string ArtistName
    {
        get { return Song.ArtistName; }
        set
        {
            if (Song.ArtistName != value)
            {
                Song.ArtistName = value;
                RaisePropertyChanged("ArtistName");
            }
        }
    }

The ArtistName Property of the View model is bound to the label like so in XAML

This is your communication between gui and code more or less. So for instance in your first example when you changed the textbox from 0 to 1, that then updates your ProductID property in your ViewModel. You can see in your ICommand GetProductCommand there is a parameter being passed to relayCommand for ProductID > 0. Now that its 1 canexecute is true so the command is now available to execute and the button becomes clickable. When you Click it GetProduct is the action that takes place and that method then sets your CurrentProduct Property with value. The Datatemplate for product information is bound to ProductModel in the xaml and ProductModel is bound to your CurrentProduct, so now inside that datatemplate the properties of CurrentProduct can be bound to xaml elements so CurrentProduct.ProductName or is bound to

<TextBox Grid.Row="1" Grid.Column="1"  Text="{Binding ProductName}" />

Its confusing at first but when you get the hang of it, it will make total sense.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top