5

I have spent few days trying to understand WPF and MVVM. It is going very slowly mostly because I have some lack of knowledge in terms of events and stuff. Here bellow I will try to explain my understanding of all this things:


Method – this one is simple and I don't think it needs any explanation. Basic ingredient in any program.

Delegate – the way I see it is pointer on method. I can think of only few applications where I would want to use it over a method.

Action – that one is even trickier. Information I have managed to find say that it is a delegate that doesn't return value... so is it just pointer on void method? I don't see point of that

Event – this one I don't get at all. It was being explained with delegate and I didn't understand how does it work and what is it for. Note I was using events writing winforms applications but it was just choosing desired event from the list.

Event handler – even more unclear.

Lambda expression – also yet another way of using method. Again I understand it doesn't return anything, I can pass some argument in it, but still aint much different from void method. I have seen some applications like when using LINQ but I still don't understand how it works.


I would like to start by saying that I understand basic construct of MVVM, what is doing what and so on. Issue I have is that I don't understand some of the code, how does it work and therefore I can't write anything actually on my own. I will be using some tutorials as example so here it goes:

S1: https://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030

S2: http://social.technet.microsoft.com/wiki/contents/articles/18199.event-handling-in-an-mvvm-wpf-application.aspx

What I am expecting from you guys is some guidance or explanation how can I approach and understand those thinks to make them at least a little less scary for me. Here I will place some examples that will hopefully show you what kind of problems I have.


1) First one comes from S1 from well known RelayCommand class:

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

I know what it is suppose to do (name speaks for itself). But I don't understand how this thing works? How it knows when to make something executable and when not. What are exactly those add and remove “commands”? I tried to read about it but it didn't help.

2) Another example form S1:

    #region CloseCommand

    /// <summary>
    /// Returns the command that, when invoked, attempts
    /// to remove this workspace from the user interface.
    /// </summary>
    public ICommand CloseCommand
    {
        get
        {
            if (_closeCommand == null)
                _closeCommand = new RelayCommand(param => this.OnRequestClose());

            return _closeCommand;
        }
    }

    #endregion // CloseCommand

    #region RequestClose [event]

    /// <summary>
    /// Raised when this workspace should be removed from the UI.
    /// </summary>
    public event EventHandler RequestClose;

    void OnRequestClose()
    {
        EventHandler handler = this.RequestClose;
        if (handler != null)
            handler(this, EventArgs.Empty);
    }

    #endregion // RequestClose [event]

Again I know what it is suppose to do, I even understand what is basically happening here but I don't see where this “thing” is actually doing something. OnRequestClose() is just creating handler that in my eyes doesn't do anything to close whatever it is suppose to close. Problem is that if I even don't see where command is executed how can I write my own commands.

3) I think this will be last example, this time from S2:

public ViewModel()
{
    _clickCommand = new DelegateCommand<string>(
        (s) => { /* perform some action */ }, //Execute
        (s) => { return !string.IsNullOrEmpty(_input); } //CanExecute
        );
}

Here problem is pretty simple. It is creating command using RelayCommand ctor (or at least it's version in this project, here called “DelegateCommand”). I don't understand those (s) and use of lambda. What is it for?


Of course that isn't everything I have problem with but I think that will give idea what is my problem to anyone willing to help. I tried to explain my problem as best as I can and I would really appreciate any help or guidance. Maybe I am expecting to much from myself but I feel like I need to know all that stuff in order to write anything serious.

Anyway thank you all in advance for any help.

Bielik
  • 922
  • 2
  • 14
  • 25
  • 3
    You've done a great job of putting together lot of great material to support what I think is probably best asked as several questions. What you've ended up asking is too broad - an answer here would be epically long. You should break this question done into smaller parts and ask them separately, but I suspect that each part has been asked and answered. You probably need to write up a question relating to each part, with some code you've written to test your understanding, and let us know where you got stuck. Then you're likely to get some good answers. – Enigmativity Aug 08 '15 at 03:32
  • For the record, your understanding of Lambda Expressions is wrong. A lambda does not necessarily return `void` or take any specific arguments. Consider the following valid lambda expression: `() => "Hello!"` which takes no parameters and returns `string`. – Federico Berasategui Aug 08 '15 at 03:34
  • @Enigmativity I was afraid that question may be too broad but I felt that most of those things are connected each other so I decided to put it in this one large topic. When learning those things there is a problem that I understand simple x => x*x but when it comes to serious stuff it gets trickier. I will wait a little for some additional answers and if nothing appear I will use your advice and try to separate it. Thank you for your reply and suggestions. – Bielik Aug 08 '15 at 09:24
  • @HighCore Thanks for pointing it out I must have messed something up. I could have swear that I read something like that relating lambda. I guess it must have been about something else. Thank you for clarification. – Bielik Aug 08 '15 at 09:26
  • 1
    `public delegate void Action()` Yes, pointer (aka delegate) to a void method. Actions and Funcs were introduced with Linq in order to provide types for common tasks performed in Linq. Linq methods take delegates that have 0 to N arguments (the framework defines 17!! versions of each) and may/may not return a value. So Actions and Funcs were born. –  Aug 10 '15 at 13:47

2 Answers2

2

A long answer for your broad question.

Let me dig into Events and EventHandler first using a simple approach

Suppose there is a big function organized in your city which will host many famous people from your country.

Let's consider three guest's for this example
Guest one is a person who is unknown by other guests
Guest two is a famous person from your area and very few people know
Guest three is very famous across your country

Consider the following assumptions

Nobody is waiting for guest one (0 EventHandler)

There are four people who are waiting for guest two (4 EventHandler's each person is an event handler waiting to greet)

There are three security personnel and 10 guests (out of which one person is also waiting for guest 2) waiting for guest 3 (13 EventHandler's)

Scenario 1 When guest one arrives at the venue (Event raised) nothing happens

Scenario 2 When guest two arrives at the venue (Event raised) the four people move towards him/her and give greetings

Scenario 3 When guest three arrives (Event) you will see security forces providing cover and ten people move towards him/her and give greetings

Simple points to be observed
1. Event is just a notification that something has happened (like a delegate with a method signature)
2. EventHandler is an action as to what happens when a specific event has happened ( a method which implements the method signature defined by the delegate)
3. One event can have many eventhandlers (e.g.. scenario 2,3). Hence the syntax += in the below code sample

The below code will answer some of your basic questions

class Program
{
    static void Main(string[] args)
    {
        var test = new Example();
        Console.ReadLine();
    }
}


class Example
{
    //This is the event definition
    delegate void ActionDelegate(string input1, string input2);

    // Two event handler which implements the signature of the event
    void ActionMethod(string a, string b)
    {
        Console.WriteLine(a + " " + b);
    }
    void ActionMethod2(string c, string d)
    {
        Console.WriteLine("Wow one more function called with parameter {0} and {1}", c, d);
    }

    delegate Tuple<string, string> LamdaDelegate(string input1, string input2);
    public Example()
    {
        //Did not declare any delegate member variable explicitly.
        //Clean and easy to understand
        Action<string, string> action = ActionMethod;

        // Had to define the delegate with method signature explicitly before using it
        ActionDelegate actionDelegate = ActionMethod; 
        actionDelegate += ActionMethod2; // Attaching more event handlers to the event

        //The below lambda expression implicitly means that it will take two inputs each of type string
        // and does not return anything. 
        //The type information is implicitly derived from the method signature of the delegate
        actionDelegate += (a, b) => Console.WriteLine("Called using lambda expression");


        //Below is a Lambda expression in which s and e each is of type string 
        //Since the return type of the delegate is Tuple<string,string> the same is returned by the expression
        //Lambda expression is using a delegate without defining a delegate explicitly. 
        LamdaDelegate myTuple = (s, e) => { return Tuple.Create(s, e); };

        //The above Lambda can be rewritten as
        myTuple += delegate (string a, string b) { return Tuple.Create(a, b); };

        //Invoking the event handlers. The event handlers are executed automatically when ever the event occurs 
        action("Hi", "called from action");
        actionDelegate("Hi", "called using explicitly defined delegate");
    }
}

Why should we use delegates?
In the above example you saw that the ActionMethod is used by two different delegates(read Event). Without delegates the above example would be dirty and unreadable.
The above example also shows Action which simplifies the need to define delegates explicitly.

Now comming to Commands
In MVVM the traditional event is replaced by Command and the event parameters (read delegate method signature) is replaced by CommandParameter

In your 3rd question the DelegateCommand has a type parameter which is string. So the (s) you see is a variable which stores the input string sent from UI. Now it is upto you to decide if you want to use the input (s) or ignore it all together. In the CanExecute part you can see that even when the input (s) is passed it has ignored it and uses the other member variable _input.

The 2nd question an event RequestClose is defined which is attached an event handler in Figure 7 of the link. Also observe that in the same figure the MenuItem is bound to the CloseCommand in the ViewModel.
So now when you click on the MenuItem the CloseCommand is invoked and it then calls the function OnRequestClose. The first thing this function checks is that is there anyone interested(read listening) in the event RequestClose which the MainWindow is listening and hence calls the window.Close()

For more clarification please do let me know.

EDIT

The code example above was just for Action<T> and delegate.

In layman terms let me put it this way

If I want to do something based on some external action I would use Event . I will just define an event and wire it up to an EventHandler and just wait for the action to occur. (In the example above I don't know when will the guest arrive but whenever they do arrive the EventHandler will respond automatically)

On the other hand I will use delegate if I want to call single/multiple functions simultaneously based on some internal condition defined in the code. In the code example above you can see that I had to invoke the delegate manually.

Please ignore the Tuple as it is just a return value with no actual importance.

EDIT 2

The scenario (_) or (s) is similar. Both mean that you will get a parameter as an input but in the first scenario the developer is trying to say that this parameter will not be used or ignored while in the (s) they intend to use it

You can't use just () as this means that the lambda expression does not contain any input parameter which is wrong since the definition says that it will receive a string as an input.

Sandesh
  • 2,966
  • 1
  • 20
  • 34
  • Thank you for your reply, it is very helpful and explains a lot. I still have some questions though but I think I will try to read again what you wrote couple of times and do some research before asking them. Anyway thank you once more for your reply and be sure I will write again with some questions. – Bielik Aug 08 '15 at 22:04
  • And be sure I will try to answer it :-) – Sandesh Aug 09 '15 at 03:43
  • I would like to start with by saying I don't actually know what that Tuple is. I started reading something but it seems to be quite complex and I want to focus on one thing at the time. Issue with events that you showed me is that I see no difference at all from multicast delegates I tried to search something about that including this question: http://stackoverflow.com/questions/563549/difference-between-events-and-delegates-and-its-respective-applications But it didn't actually answer my question especially that from your answer they look exactly like those multicast delegates. – Bielik Aug 09 '15 at 18:23
  • Thank you for another clarification. One thing still bothers me with my 3rd question (the lambda one) is that I tried experimenting with it and it in fact accepts _ => ... as well as this (s) => ... but when I try () => ... it does not. I've read a little about differences between _ and () but still didn't helped figuring out why () doesn't work with it. I would be grateful for explaining differences between those 3 and perhaps some other forms if they exist. – Bielik Aug 10 '15 at 15:26
  • Ok thank you I think I understand now most of it. The greatest mystery now is that first example with CanExecuteChanged, still can't figure out how it works. I assume that this is somehow connected with PropertyChanged event that @Liero mentioned in comment to previous answer but I think this is really subject for another question. – Bielik Aug 11 '15 at 12:12
2

1. Delegate

the way I see it is pointer on method

Correct. However since C# is strongly typed, you need to define, what parameters and return type must the method have. This is what delegates are.

I can think of only few applications where I would want to use it over a method.

This is not about method vs deledate. When you need to pass method as a parameter, then the parameter is defined using delegate.

2. Action

Action is concrete type of delegate. While delegate can refer to any method, Action says, that it is parameterless method with return type void. Action<string> means that parameter is of type string. Action<string, int> means that the method's first parameter must be of type string and second of type int.

Another concrete example of delegate is Func delegate. Func<bool> means that the method does not have parameters and returns bool. Func<string, bool> means that there is one input parameter of type string and it returns bool.

EventHandler is just another delegate, that represents method with void return type and two input parameters: object and EventArgs

3. Event

just think about Button.Click event. The programmers at microsoft that worked on Button class had to provide a way how to notify your program, that button was clicked. So they defined an event and you can handle the event by providing a method that will execute when the event occurs. The method is called eventhandler.

4. EventHandler is either used as common name for methods that are assinged to events or it is concrete delegate that defines input and output parameters or it is used as.

e.g: Button.Click += DoSomehing; Click is an event. Method DoSomething is and eventhandler. Is must return void and have two input parameters of type object and EventArgs, because when you look at the definition of click event, you can see concrete delegate type which is EventHandler (or RoutedEventHandler - just another delegate used in WPF in some events).

5. Lambda expression

is very simple. Lambda expression is just another syntax to write a method. Compiler translates lambdas to methods anyway. Lambdas are just syntactic sugar.

following method and lambda are equal

bool IsGreaterThan5(int number)
{
  return number > 5;
}

var isGreaterThan5 = new Func<int, bool>(number => number > 5);

for example, if you have an array of integers, then you can use Where linq extention method to filter the array. Intelli sense tells you, that the parameter of Where method is Func<int, bool>. Therefore you need to pass method that takes one parameter of type int and returns bool.

int[] numbers = new []{ 1, 2, 3 4, 5, 6, 7 };
var filteredNumbers = numbers.Where(IsGreaterThan5); //method IsGreaterThan5 is defined in previus example

//just another syntax:
var filteredNumbers = numbers.Where(number => number > 5);

//just another syntax:
var filteredNumbers = numbers.Where(new Func<int, bool>(number => number > 5));

//just another syntax:
Func<int, bool> isGreaterThan5 = i => i > 5; //it does not matter how you name the input parameter
var filteredNumbers = numbers.Where(isGreaterThan5);
Liero
  • 25,216
  • 29
  • 151
  • 297
  • Thank you also for great answer and putting it all together. There is still thing about events that bothers me. I understand the simple definition that this is notification but it seems there remain something unnoticed about them. I have managed to make simple working buttons, enabling and disabling areas using properties in MVVM but those events I can't see them clearly. I still don't know how to create specific event for example that will notify whenever someone presses arrow button. I couldn't find it in google so I assume that there is something wrong with my understanding of them. – Bielik Aug 10 '15 at 15:36
  • Usually you don't need to define your own events. You don't need to notify anybody that someone pressed arrow button, because there is WPF framework that fires those notifictions, for example `Window.KeyPress` event. You just need to write what should happen when the event occurs. – Liero Aug 11 '15 at 07:25
  • 1
    In WPF, there is specific event called `PropertChanged` that notifies the databound UI controls to update themself when the source object changes. In this case you have to trigger the event when you change something in viewmodel and WPF is attached to the event and handles it. So this is opposite of the previous scenario with keys Please notice, that events, delegates etc are not specific to MVVM, neither WPF. You are trying to swallow two bites at once. – Liero Aug 11 '15 at 07:25
  • Thank you again for answer. It seems this PropertyChanged and stuff I mention in my comment to another answer is bigger subject and I would like to know more. Do you have any link to solid but not too sophisticated article about that so I could understand? Actually I would be grateful for any materials that would help me to know framework better. Now I am just walking blind only googling what I actually need at the moment. It's fine but it would be better to have some more at least basic knowledge what i can actually do in my projects. Thank you in advance. – Bielik Aug 11 '15 at 12:24
  • PS. There is simple mistake in your answer (I think). When you have method IsGreaterThan5 the return type should be bool not void. – Bielik Aug 11 '15 at 12:25
  • true, fixed. sorry if it confused you. Regarding the PropertyChanged, ask a new question and notify me here in comment so I can answer it – Liero Aug 11 '15 at 13:01