Win Phone App: Possible to use event declared on another page? - c#

My scenario is quite simple, in fact I thought it would cause no problem but it does, can anyone help?
My MainPage begins with this:
namespace PhoneApp
{
public partial class MainPage : PhoneApplicationPage { /* snip */ }
}
Later in the page is this simple method:
private void MakeSound(object sender, MouseButtonEventArgs e)
All right, everything is fine.
But on my SettingsSample.xaml I have a ListBoxItem that calls the method MakeSoundvia SelectionChanged property. VS studio tells me that 'event handler MakeSoundis not found on class PhoneApp.SettingsSample '
The code for this page begins with:
namespace PhoneApp
{
public partial class SettingsSample : PhoneApplicationPage { /* snip */ }
}
Copying the code of the method on SettingsPage.xaml.cs doesn't work for some reason, but I feel like it should possible to use the method described on MaingePage.xaml.cs, especially since their respective code resides in the same Namespace.
I tried to add
using PhoneApp;
on SettingsSample.xaml.cs. Not exceptionally clever, but I have no other idea

Your event function should read EventClickOnMyListBox and be located in the code-behind for your page. This function would then call your makeasound function (that you can put wherever you want). And it could be called by another event or function.
There is a semantics distinction between the event itself and what the event does. Your event is not makeasound, your event will cause a sound to be made, among possible other things.
If ever you want to add a popup to add a visual effect, you'll be stuck if you called directly the makeasound function, whereas you'll just have to add a line to your EventClickOnMyListBox in the other scenario.
That's why xaml works that way, and allows you to refer only to object in the enclosing class (or if there is a way I don't know it / and never needed it). You should minimize code-behind code (this is the way of thinking of the MVVM pattern if you want to go further down this road).
Replying to your comment, here is some code to get you started:
Your event should be in the code-behind of your SettingSample page, and should call the makeasound function instead of being the makeasound function:
private void MenuItem_Click(object sender, MouseButtonEventArgs e)
{
Whatever.Myclass.MakeASound (blabla); // So typically MakeASound would be static
}
And now same thing in your main page: you do not use your private void MakeSound(object sender, MouseButtonEventArgs e) as the event for a click, but an event handler just as the one above.
Take a step back and you'll see it's very natural: you want two things to do the same. But one thing cannot be the exact same thing as the first, for language-related reasons (read about C# and XAML to understand why).
So you put your feature in a third component, accessible from the first two. And you call this component from each of them. This way, they both share access to the same feature, and everybody is happy.

Related

Access method of an usercontrol from another usercontrol

On my form I have 2 UserControls (ButtonDiscount, ButtonAdvertisment) that inherit FadeControl. FadeControl inherits UserControl class and is used to do custom stuff on the controls like fade out.
My 2 UserControls each have just one button hence those two unimaginative names.
On click of that button on one of usercontrols, I need to access the method in FadeControl from the other UserControl. The other button does the opposite.
I've done the following, on the event click in the UserControl ButtonDiscount:
private void button1_Click(object sender, EventArgs e)
{
ButtonAdvertisment ba = (ButtonAdvertisment)this.Parent.Controls.Find("buttonAdvertisment1", true)[0];
ba.FadeOut(true);
}
It works like a charm, but I don't think this is the right way, is there another way to access the method from the parent class of the other UserControl?
I can't pass it thru a UserControl constructor, the designer breaks down every time.
You have 2 separate user controls which are not aware of each other, which is good and keeps your code loosely-coupled. Now what you are trying to do is to make them somehow know about each other and communicate. Making them aware of each other breaks the loose-coupling and is a bad design.
What I would suggest is creating a 3rd control which will hold the two together and will handle all the communication between them. Each of your original controls will have public events, to which the parent control can subscribe and handle appropriately.
Check mediator pattern for more info: http://en.wikipedia.org/wiki/Mediator_pattern
What you've done is fine - you could do it by exposing events that fired when you click the button in those controls, and then passing references to each other (subscribing to those, writing the code to fade 'this' control).
That might be a bit too much work for a simple solution, however.
What I would say about your solution is that if you were to change the name of control(s) then it stops working. You could instead do:
var ba = this.Parent.Controls.OfType<ButtonAdvertisement>().FirstOrDefault();
That way you're no longer tied to the control name - but the type of the control. You'll need a using System.Linq; in your code file for this to work. Of course, this relies on the fact that there is only ever one other instance of that control type in the parent.
If you're interested in the first solution I mentioned - then this code snippet should help demonstrate:
public class FadeControl {
public event EventHandler Clicked;
public void FadeOut(bool b){
}
public void AttachTo(FadeControl other){
//splitting this operation to a public and private allows us to
//initiate an attach publicly, but then recurse privately without
//causing a stack overflow
AttachToInternal(other);
other.AttachToInternal(this);
}
private void AttachToInternal(FadeControl other){
other.Clicked += Attached_Clicked;
}
protected virtual void Attached_Clicked(object sender, EventArgs e)
{
//fade me out
FadeOut(true);
}
// provides a way for the deriving class to raise the Clicked event
protected void OnButtonClicked(){
if(Clicked != null) Clicked(this, null);
}
}
public class ButtonDiscount : FadeControl {
Button _button;
//omitted: designer code
//this is your handler for the _button clicked event
private void _button_Clicked(object sender, EventArgs e){
//call the base class' OnButtonClicked method - to raise the event
OnButtonClicked();
//TODO: do work.
}
}
//omitted - code for the ButtonAdvertisement class
Once you have that done - in your form, assuming you have _buttonAdvertisement and _buttonDiscount members in your form and after they're initialised - you simply do:
_buttonAdvertisement.AttachTo(_buttonDiscount);
And that will immediately bind both controls to each other.
Note - in response to a comment below - I've made the event handler in FadeControl for another FadeControl's Clicked event protected and virtual - so you can override it.

asp.net OnClick events for controls

I'm converting a VB project to C#, and I notice that in vb it will call a function like:
Protected Sub WZTestResult_NextButtonClick(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.WizardNavigationEventArgs) Handles WZTestResult.NextButtonClick
which handles the next button click event for a wizard.
In c# I have to add the line:
OnNextButtonClick="WZTestResult_NextButtonClick"
on the asp.net source page or it will never hit the function. Is this a necessity in c#, or is there something that I'm overlooking or missing? Basically, is there a way in c# for it to hit that function like in VB without adding the line above in the source page?
There is no equivalent for VB's Handles keyword.
You can do it in code behind if you want, when the page is initialized
public Default() {
this.Init += (_o, _e) => {
this.Wizard.NextButtonClick += WZTestResult_NextButtonClick;
}
}
Default is the page constructor.
Generally speaking the IDE will take care of most of this for you. If you add a button to a form in the Visual Studio designer and double click on that button it will take you to the event handler for that control in the code (the click event in this case).
private void button1_Click(object sender, EventArgs e)
{
}
You'll notice that the file you're in doesn't contain the code that attaches this method to the control event. Visual Studio splits the form into a partial class that contains your code and a generated class that contains auto-generated wiring code. In the solution explorer that looks like this:
Form1.cs -> the file that you'll add code to
Form1.Designer.cs -> the auto-generated designer file
You don't want to change the .designer.cs files because changing the form in the visual designer might overwrite your changes. You'll just work in the Form1.cs file and you'll likely never even see the event assignment code.
So the answer to your question is no, with the caveat that you'll rarely ever have to add or see this code:
this.Wizard.NextButtonClick += WZTestResult_NextButtonClick;

Find the right parameters for an event without using Design Mode in Visual Studio 2010

Is there a way to know what parameters are needed by an event in Visual Studio 2010?
Let's say I have a DropDownList control and I want to bind a method to the "OnSelectedIndexChanged", I would do something like this
In the ASPX File:
<asp:DropDownList ID="lstMyList" runat="server" OnSelectedIndexChanged="lstMyList_SelectedIndexChanged"></asp:DropDownList>
In the codebehind:
protected void lstMyList_SelectedIndexChanged(object sender, EventArgs e)
{
...
}
Is there a way to know what parameters the method needs? (In this case, an object for the sender and an EventArgs parameter for the event.)
I know you can easily create the method by double-clicking the right event in Design Mode, but it does a mess with your code so I prefer not to use it.
Thanks!
You can find out the parameters by "going to definition" (F12) on the appropriate event, finding out what delegate type it uses, then going to definition on that. In this case the SelectedIndexChanged event has type EventHandler which is defined as follows:
[SerializableAttribute]
[ComVisibleAttribute(true)]
public delegate void EventHandler(
Object sender,
EventArgs e
)
You can also find this information by searching the web or pressing F1 and searching in the help.
I know you can easily create the method by double-clicking the right event in Design Mode, but it does a mess with your code so I prefer not to use it.
I think you should try to overcome your fear of using the designer. You are most likely wasting more time in lost productivity by not using the code generation features in Visual Studio than the potential time you might have saved by protecting yourself against the designer messing up your code.
Hardly economical in terms of keystrokes and productivity but a possibility, if you're finding the event in code to 'Go To Definition' anyway, and imagining for a moment that you don't mind using the code editor features of VS, too, is to hit the Tab key, then add the += before hitting the Tab key another two times. This will generate the appropriate delegation and method definition, which will result in you seeing the method signature.
For instance, typing the following, tabbing appropriately (twice after typing '+='):
MyType.MyEvent += new System.EventHandler(MyType_MyEvent);
Generates a method like the following:
void MyType_MyEvent(object sender, EventArgs e)
{
throw new NotImplementedException();
}
Now, the productivity reduction could occur if you don't actually require both pieces of code.

In Silverlight, what's the difference between UserControl_Loaded and Page_Loaded?

I'm trying to write a silverlight application that takes in InitParams and then uses those InitParams to make a change to the Source of the MediaElement on the page. I'm trying to figure out the proper place to put my code.
I watched Tim Heuer's excellent video on InitParams, but in the video (which was for Silverlight 2), it shows the following on the Page.xaml.cs:
void Page_Loaded(object sender, RoutedEventArgs e)
{
}
I don't see Page_Loaded when I open MainPage.xaml.cs, and I'm wondering if that was automatically created in the Silverlight 2 SDK and left out of the Silverlight 3 SDK. Or perhaps Tim added that in his video manually.
I find that I can go into the opening UserControl tag of MainPage.xaml and add Loaded="<New_Event_Handler>" which creates the following in MainPage.xaml.cs:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
}
By default, there's also the following in MainPage.xaml.cs, which is run during the Application_Startup event in App.xaml.cs:
public MainPage()
{
InitializeComponent();
}
I need to figure out where is the best place to insert my code to change the Source on my MediaElement in my xaml. Should I put it in MainPage? Should I add the Loaded event handler and put it into UserControl_Loaded? If it's supposed to be Page_Loaded, where do I find that in Silverlight 3?
Any help would be much appreciated.
"UserControl_Loaded" and "Page_Loaded" are just method names and the names don't matter (you could name the method "Foo" if you wanted). What makes these methods do anything is the fact that they are attached to the Loaded event on the UserControl (which is what you did when you edited the MainPage.xaml file).

ASP.NET UserControl's and DefaultEvent

Outline
OK, I have Google'd this and already expecting a big fat NO!! But I thought I should ask since I know sometimes there can be the odd little gem of knowledge lurking around in peoples heads ^_^
I am working my way through some excercises in a book for study, and this particular exercise is User Controls. I have cobbled together a control and would like to set the DefaultEvent for it (having done this for previous controls) so when I double-click it, the default event created is whatever I specify it to be.
NOTE: This is a standard User Control (.ascx), NOT a custom rendered control.
Current Code
Here is the class & event definition:
[System.ComponentModel.DefaultEvent("OKClicked")]
public partial class AddressBox : System.Web.UI.UserControl
{
public event EventHandler OKClicked;
Current Result
Now, when I double click the the control when it is on a ASPX page, the following is created:
protected void AddressBox1_Load(object sender, EventArgs e)
{
}
Not quite what I was expecting! So, my question:
Is it possible to define a DefaultEvent for a UserControl? Is it a hack? If it's [not] supported, is there a reason?
Side Note: How do we put underscores in code? I cant seem to put and escape char in?
Here is a possible answer, without testing (like martin did).
In reflector, you will see that the DefaultEventAttribute allows itself to be inherited.
In reflector, you see that the UserControl class has it's default event set to the Load event.
So the possible reason is that even though you are decorating your user control with the default event of OKClick, VS might still be thinking that the default event is load, as it's being inherited from UserControl whose default event is Load.
Just a high level guess at what might be happening.
OK, I checked this out, Inheriting from WebControl rather than UserControl.. All worked fine.
Looks like Darren Kopp takes the crown for this one! Thanks for the input!

Categories