-2

Isn't it possible to create the name associated to the _Click action while the button hasn't been created in beforehand? It's a little hard to explain but I think it gets clearer while skimming through my code:

index = Array.FindIndex(bookmarks, i => i == null || i.Length == 0); //find closest empty spot in array
bookmarks[index] = "http://" + Urlbox.Text;
book[index] = new Button();
book[index].Height = 31;
book[index].Content = bookmarks[index];
book[index].Click += book[index]_Click;
Bookbar.Items.Add(book[index]);

My method as follows:

public void book[index]_Click(object sender, RoutedEventArgs e)
{

    WebBrowser1.Navigate("random url");
}

As you can see, my button is programmatically created before I try to add an action to it. However, I'm getting the wierd error Error 1 ; expected under the line creating my action. Although, changing that line to book[index].Click += Bookmark_Click; where Bookmark is in beforehand an existing button seems to work just fine.

The reason im using arrays is that I want to create multiple buttons and give each one of them a different _Click action. What am I doing wrong?

manske
  • 25
  • 1
  • 5
  • 2
    It's simply incorrect syntax: `book[index]_Click`. `book[index]` is `Button` and you can't use it other way. – Anatolii Gabuza Jan 09 '14 at 09:41
  • What do you mean? I can create actions with that syntax with already in beforehand existing buttons, what is wrong? – manske Jan 09 '14 at 09:42
  • 2
    @manske to add an event handler you have to give a **method name**. There...you're trying to build a method name from an instance? It's just C# syntax...create a bookButton_Click() method and attach all click handlers to it. – Adriano Repetti Jan 09 '14 at 09:43
  • Can you describe what do you want to achieve by that? – Anatolii Gabuza Jan 09 '14 at 09:44
  • @manske Do you think `book[index]_Click` is a **valid method name** in C#? – Adriano Repetti Jan 09 '14 at 09:49
  • @Adriano How do I attach handlers to it? I've edited the main post. Sorry for not know, it's not my area of expertise. – manske Jan 09 '14 at 09:49
  • **Don't create or manipulate UI elements in procedural code in WPF. That's what XAML is for.** – Federico Berasategui Jan 09 '14 at 09:50
  • As I said in my previous comment. You don't need to create different methods for every button you'll add at run-time. One method and you'll get original button in `sender` parameter. Rename your method, for example, `buttonBook_Click` and it'll work. – Adriano Repetti Jan 09 '14 at 09:51
  • @Adriano Well, `Bookmark_Click` seems to be? Why can't I use a custom name for my click actions? – manske Jan 09 '14 at 09:51
  • @manske The "thing" attached to the `Click` property must be a method. that has to be defined somehow. It does not magically appear, just because you are adding something to `Click`... – EricSchaefer Jan 09 '14 at 09:52
  • @manske Because you can't (let me simplify) create a method at run-time. Method is a compile-time thing, object instances are run-time thing. You can bind an event of an object instance to a method at compile time (creating that instance dynamically). – Adriano Repetti Jan 09 '14 at 09:52
  • @manske seems like you need to learn `C#` and `OOP` by creating some `Hello, World!` stuff in console applications before you try to create complex, dynamic, WPF-based UIs. You don't even seem to understand the basics of method calls and event handlers. – Federico Berasategui Jan 09 '14 at 09:53
  • And again, WPF UIs are done in XAML, not procedural code. WPF is a complex framework which requires a strong knowledge of OOP concepts in order to understand the MVVM pattern, not really suitable for the unexperienced. – Federico Berasategui Jan 09 '14 at 09:54
  • @Adriano Could you give me an example? Can I bind a method to a random existing button and then use it? I thought renaming the method was my problem from the beginning. – manske Jan 09 '14 at 09:58
  • Well maybe @HighCore has been little bit too _direct_ but I agree on one point: stop, sit down and go back to introductory tutorials. You'll nearn stronger basics, a WPF application involves too many concept to be a good starting point – Adriano Repetti Jan 09 '14 at 09:58
  • 1
    @UriY's answer (and new AlSki's answer too) are pretty right. It's what you have to do (in this case). – Adriano Repetti Jan 09 '14 at 09:59
  • @HighCore I beg to differ. If you know what you are doing, you can create WPF controls dynamically. E.g. Assume you want to have a button in your window for every file in a certain folder... – EricSchaefer Jan 09 '14 at 09:59
  • @ericschaefer that's what an `ItemsControl` is for. WPF is not winforms, and the archaic ways of winforms are not welcome in WPF. – Federico Berasategui Jan 09 '14 at 10:00
  • @HighCore You clearly have not built very complicated GUIs, have you? An ItemsControl would not give you the kind of control over the GUI that is needed sometimes. – EricSchaefer Jan 09 '14 at 10:03
  • @HighCore I cannot simply understand what you benefit of telling me that. I know it is a hard task for me to acheive but one should be able to ask without reading useless crap. If you think I dont have the right knowledge and only want to crap me down you do not have to write at all. – manske Jan 09 '14 at 10:03
  • 1
    @manske I'm not trying to benefit myself, I'm trying to help you. You are trying to run before you can even walk. Think again, my friend. – Federico Berasategui Jan 09 '14 at 10:04
  • @EricSchaefer I can do [any sort of UI](http://stackoverflow.com/a/15821573/643085) with an `ItemsControl`. Go ahead and show me an example of a UI that needs procedural code in WPF. – Federico Berasategui Jan 09 '14 at 10:05
  • @HighCore Could not agree more (learn to walk first)... – EricSchaefer Jan 09 '14 at 10:06
  • @HighCore Or, you could at least give me a hint like the answers I got. I cannot see how your comments are helping me solving my problem. I do not want to skip the problem, I want to solve it. – manske Jan 09 '14 at 10:09
  • @manske the **best** advice I can give you is what I tell to everyone else trying to use WPF this way: Learn MVVM before you ever write a single line of code in WPF. – Federico Berasategui Jan 09 '14 at 10:11
  • @HighCore I am talking about 20 levels deep nested custom controls which can completely change any time an external event occours. The example you link to is rather trivial compared to that. Think "highly dynamic, customizable HMI/SCADA applications". The level of dynamism you need for that simply can not be achieved in a declarative style. At least not in a maintainable way. – EricSchaefer Jan 09 '14 at 10:17
  • @HighCore Maybe see it this way: How do you think ItemsControl is implemented? – EricSchaefer Jan 09 '14 at 10:19
  • @ericschaefer regarding your first comment, I see that as a series of `HierarchicalDataTemplates`, I don't care how deep. regarding your second comment, it is not up to me "how ItemsControl is implemented" - as I also don't care how `System.String` is implemented. I just know how it works in my code. – Federico Berasategui Jan 09 '14 at 10:37
  • @ericshaefer and yes, googling "SCADA" in google images the only thing I see is a bunch of ItemsControls. – Federico Berasategui Jan 09 '14 at 10:38

3 Answers3

2

You can't write

book[index].Click += book[index]_Click;

The syntax is just wrong.

You need to prepare one handler to all the buttons and use the sender parameter to differentiate between them. Example:

void buttonBook_Click(object sender, EventArgs e)
{
    // implementation...
}

You have to register this handler as follows:

book[index].Click += buttonBook_Click;
Uri Y
  • 840
  • 5
  • 13
2

First, you cannot use [] in the name of a method, which is your error.

However by the looks of what you are doing, each button is simply navigating to a different url. This isn't a different operation, simply a parameterised one.

There are several ways to get round this, this simplest is a method which pulls the url back out of the button

public void book_Click(object sender, RoutedEventArgs e)
{
  // since we copied this already
  WebBrowser1.Navigate(new Uri(((Button)sender).Content));
}

Alternatively you can also use an anonymous method, this relies on a closure (index being captured at the time the anonymous method is created).

book[index].Click += (sender, e) { WebBrowser1.Navigate(bookmarks[index]); };
AlSki
  • 6,868
  • 1
  • 26
  • 39
  • I think I get it. Thank you! – manske Jan 09 '14 at 10:06
  • Hi again, trying your first solution didn't really help out. I get the error `Error 1 The best overloaded method match for 'System.Windows.Controls.WebBrowser.Navigate(System.Uri)' has some invalid arguments` what am I doing wrong now? – manske Jan 09 '14 at 11:19
  • Currently the url is in a string, all you need to do is change it to a Uri. Updated above – AlSki Jan 09 '14 at 12:28
0

Problem is that book[index]_Click is incorrect method name so you can't use it as an event handler. You can use anonymous functions instead:

book[index].Click += (s, r) { WebBrowser1.Navigate("random url"); };
Anatolii Gabuza
  • 6,184
  • 2
  • 36
  • 54
  • 1
    Why an anonymous function? He may use it but there is no **need** for that (and this won't _teach_ him the reason what he's doing is wrong). – Adriano Repetti Jan 09 '14 at 09:54
  • I wouldn't use anonymous functions for GUI event handlers, because this way you do not have any means of detaching them from the event, should that ever be needed. – EricSchaefer Jan 09 '14 at 09:55
  • @Adriano, I'm not saying that this is proper way. But the question was how can he achieve this. – Anatolii Gabuza Jan 09 '14 at 09:57
  • @EricSchaefer Do we need to detach those handlers from event?! I don't think so. Of course there are some specific cases, but not this one. – Anatolii Gabuza Jan 09 '14 at 10:13