Handling Delegates on Windows Phone - c#

I'm having a problem with the QueryString in my application.I have two buttons in my mainpage, when the user clicks on a button, the application navigates to the second page and stores the button ID on the Querystring.
Now, the problem I'm having is that if a user clicks on a button the Querystring "ID" key is set to the corresponding ID value BUT that value of ID then becomes persistant.
ie
Click Button1 => NavigationService("/Page2.xaml?ID=1",UriKind.Relative) => Check incoming ID value in onNavigated event of page2 and youu find that Querystring successfully set to ID in the second page.
but if you click the back button then press button2
Click Button2 => NavigationService("/Page2.xaml?ID=2",UriKind.Relative) => Check QueryString value in onNavidated event on page2 and you find that the ID key still as a value of 1.
If I had started off by pressing button2 then the ID key would have a persisted value of 2.
I have absolutely NO idea what could be going on.I have animated page transition between pages but I don't know how that could affect things.Does anyone have any ideas of what could be happening? Is there a way of reseting the whole app if I navigate back to the mainpage?
In MainPage
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
animation1.Stop();
animation2.Stop();
animation1.Begin();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
animation2.Begin();
animation2.Completed += (x, y) => NavigationService.Navigate(new Uri("/fooApp;component/Page2.xaml?id=1", UriKind.Relative));
}
private void button2_Click(object sender, RoutedEventArgs e)
{
animation2.Begin();
animation2.Completed += (x, y) => NavigationService.Navigate(new Uri("/fooApp;component/Page2.xaml?id=2", UriKind.Relative));
}
private void button3_Click(object sender, RoutedEventArgs e)
{
animation2.Begin();
animation2.Completed += (x, y) => NavigationService.Navigate(new Uri("/fooApp;component/Page2.xaml?id=3", UriKind.Relative));
}
In Page2
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e )
{
base.OnNavigatedTo(e);
animation1.Stop();
animation2.Stop();
animation1.Begin();
}
By the way I have commented out the entire Page2 Page Loaded event.
UPDATE
One thing I have noticed is that the program doesn't even run the second Navigation call, it only runs the first, I know this because if I change the Uri source in button2 to an empty string and run the program with button1 being the button that is pressed first, I will get the querystring value stuck at 1 no matter which button I go back and press.When I look into the NavigationEventArgs e object in the OnNavigatedTo event in page2, it's URI source will always be the first uri source.
My guess right now is that the animation2.Completed event is acting as some sort of multicast delegate of sorts, Whatever gets put first into it is whatever will get run.Also, I removed the animations and just had the Navigation statement, the program worked fine but without the animation.Does anyone know how I can clear the animation2.Completed event? Or have any ideas on an alternate implementation.

Basically, you're adding a Completed handler to your storyboard. The Completed handler navigates to page 2. Then you go back, and press the second button. Since you went back to previous page, you're re-using the same page instance, and therefore the same Storyboard instance. Now you're adding a second Completed handler to your Storyboard. So when the animation finishes, the Storyboard has two Completed handlers, the first one gets executed first, thus navigating to Page2 with the first parameters.
Instead of adding a Completed handler every time, just do it once for all, and store the URL in a property:
In your XAML:
<Storyboard x:Key="Animation2" Completed="Storyboard_Completed">
<!-- whatever-->
</Storyboard>
Then in your C# code:
protected string Uri { get; set; }
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
animation1.Stop();
animation2.Stop();
animation1.Begin();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
this.Uri = "/fooApp;component/Page2.xaml?id=1";
animation2.Begin();
}
private void button2_Click(object sender, RoutedEventArgs e)
{
this.Uri = "/fooApp;component/Page2.xaml?id=2";
animation2.Begin();
}
private void button3_Click(object sender, RoutedEventArgs e)
{
this.Uri = "/fooApp;component/Page2.xaml?id=3";
animation2.Begin();
}
private void Storyboard_Completed(object sender, EventArgs e)
{
this.NavigationService.Navigate(new Uri(this.Uri, UriKind.Relative));
}
Bonus:
Removing an event handler
If you want to remove an event handler, simply use the -= operator. But then you can't use a lambda, you have to use a 'classical' method:
// Good
this.animation2.Completed -= Storyboard_Completed;
// Wrong
this.animation2.Completed -= (sender, e) => NavigationService.Navigate(new Uri("RandomText_JustWantCompletedEventToBeHit", UriKind.Relative));
Alternative implementation
If all your buttons do is to trigger the animation and redirect to Page2, then you can handle it in a more generic way thanks to the Tag property of the controls. The Tag property allows you to to store any object you want to identify the control.
XAML:
<Button Click="Button_Click" Content="Button 1" Tag="1" />
<Button Click="Button_Click" Content="Button 2" Tag="2" />
<Button Click="Button_Click" Content="Button 3" Tag="3" />
C#:
private void Button_Click(object sender, RoutedEventArgs e)
{
var element = (FrameworkElement)sender;
this.Url = "/fooApp;component/Page2.xaml?id=" + element.Tag.ToString();
animation2.Begin();
}

Related

C# Form - MouseClick will click the actual control after losing form focus

If you ever remove focus from any professional application like Chrome/FireFox/Visual Studio, and then reclick a button/menu item, it will actually click it as if you never lost focus.
How can I apply the same concept in C# WinForm? I tried many things like
private void form1_MouseClick(object sender, MouseEventArgs e)
{
BringToFront();
Activate();
}
Activate/focus/select/etc... nothing worked to react the same way, it always takes 3-4 clicks to actually click on a menu!
I thought about making a click event for every single control, but that seemed rather redundant.
Check this for example (Yellow Clicks)
You are right about Menues taking an extra click to get focus.
Which is extra annoying since the menue get highlighted anyway but doesn't react to the 1st click..
You can avoid that by coding the MouseEnter event:
private void menuStrip1_MouseEnter(object sender, EventArgs e)
{
// either
menuStrip1.Focus();
// or
this.Focus();
}
The downside of this is, that it is stealing focus from other applications, which is not something a well-behaved application should do..
So I think it is better to wait for a definitive user action; code the MouseDown event in a similar way..:
private void menuStrip1_MouseDown(object sender, MouseEventArgs e)
{
menuStrip1.Focus();
}
Or use the event that was made for the occasion:
private void menuStrip1_MenuActivate(object sender, EventArgs e)
{
menuStrip1.Focus();
}
I can't confirm a similar problem with Buttons or any other controls, though.
I have find trick to solve your problem. it work for me 100%
See this code:
dynamic elem1;
private void menuStrip1_MouseEnter(object sender, EventArgs e)
{
elem1 = sender;
}
private void menuStrip1_MouseLeave(object sender, EventArgs e)
{
elem1 = null;
}
private void Form1_Activated(object sender, EventArgs e)
{
if(elem1 != null){
elem1.PerformClick();
if (elem1.GetType().ToString() == "System.Windows.Forms.ToolStripMenuItem") elem1.ShowDropDown();
}
elem1 = null;
}
Here what happend.
When mouse enter button/menu item elem1 = this button/menu, and when mouse leave it set back to null.
so when form Activated we can call elem1.PerformClick() to click the button/menu item.

Running Page Load multiple times

I have a user control on an aspx page that contains filter fields and return a WhereClause. The user conrol will raise an event called FilterApplied when Search is clicked.
On my main form, I add the control with:
<uc1:Filter runat="server" ID="Filter" />
<br />
In my code behind I have:
protected void Page_Load(object sender, EventArgs e)
{
//Register event when filter is changed.
this.Filter.FilterApplied += new EventHandler(this.FilterApplied);
if (Page.IsPostBack)
{ //Do some things that take long
}
}
protected void FilterApplied(object sender, EventArgs e)
{
//Reload the page to refresh the graphs.
Page_Load(sender, e);
}
Problem is:
When I click Search on my user control, the Form_Load runs twice. Once because it is reloaded and then another time because I call it from FilterApplied. If I don't call it from FilterApplied, then the whereclause is still empty.
How can I ensure the Page_Load only run once when Search is clicked?
Your problem lays in multiple registering for FilterApplied event. Each time you call the Page_Load method, you subscribe to this event again. Here is a really simple example of what you are doing, written in WinForms with one button on the form, just to point out your problem:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private int numClicks = 0;
private void Form1_Load(object sender, EventArgs e)
{
button1.Click += button1_Click;
this.Text = numClicks.ToString();
}
private void button1_Click(object sender, EventArgs e)
{
numClicks++;
//try uncommenting and commenting next line of code, and observe the difference:
//button1.Click -= button1_Click;
Form1_Load(sender, e);
}
}

How to add page into Navigation stack?( Windows Phone)

when I navigate to Page1.xaml, I have an empty navidation stack, what I need to add into
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e){}
to add Page2.xaml into Navigation stack (I need to navidate into Page2.xaml only when I press go back button)
If I understand correctly, you want to navigate to Page2.xaml when the user press the Back button, correct?
You'll have to use the BackKeyPressed event to make that work, like so:
public MainPage()
{
InitializeComponent();
this.BackKeyPress += new EventHandler<System.ComponentModel.CancelEventArgs>(MainPage_BackKeyPress);
}
void MainPage_BackKeyPress(object sender, System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
Dispatcher.BeginInvoke(() =>
{
NavigationService.Navigate(new Uri("/Page2.xaml", UriKind.Relative));
});
}
But please be advised that changing the default behavior of the Back button may lead to fail app certification!

How can I navigate and pass data between Pages?

I'm a bit of a beginner with this so i'll try and keep it simple.
I have a a xaml page with a button click event linking it to another xaml page. What I'm trying to do is on the click event take two strings and pass them to a text box on the second page. Can you please show me a simple code example of how to do this?
On the button click event of the first page you do something like the following
private void button1_Click(object sender, RoutedEventArgs e)
{
string urlWIthData = string.Format("/Page2.xaml?name={0}", txtName.Text);
this.NavigationService.Navigate(new Uri(urlWIthData, UriKind.Relative));
}
On the desintation page, you do the following:
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
myTextBox.Text = this.NavigationContext.QueryString["name"].ToString();
}

Calling page event when ASP.NET user control event is invoked

Suppose there is a user control in a page called Paging.ascx that is embedded in PageWithResults.aspx. This control has the necessary properties to keep track of various details about what page you're on (ie: CurrentPage, TotalRecordsInResults, RecordsPerPage, etc..). It also contains events that fire off when you click on a hyperlink ("next page" or "previous page"). Example below. I need to tell PageWithResults.aspx that one of these LinkButton web controls was clicked. I think I need to assign a delegate in the page, so that when this user control event is called (hyperlink is clicked), it also calls some other method/event in the page class. That way I can quickly check what the new value of CurrentPage is (based on what was called in the event below) and get a new result set for the new page (based on the CurrentPage property). But I'm not sure of the best approach. I'm thinking this will require a delegate, but I'm not sure how to wire it up. If you need more details, please ask.
protected void btnNext_Click(object sender, EventArgs e)
{
this.CurrentPage = this.CurrentPage + 1;
if (OnPageChanged != null) OnPageChanged(this.CurrentPage);
}
I'm thinking I have to put my delegate here somewhere. ??
protected void btnNext_Click(object sender, EventArgs e)
{
this.CurrentPage = this.CurrentPage + 1;
if (OnPageChanged != null) OnPageChanged(this.CurrentPage);
//delegate to call object.method or something
}
Using an event would work fine.
You would create the event within your UserControl like so:
public event EventHandler ButtonClicked;
Then invoke the event when required:
protected void Button1_Click(object sender, EventArgs e)
{
if (ButtonClicked != null)
ButtonClicked(this, new EventArgs());
}
In your page you would need to assign an event handler:
protected void Page_Load(object sender, EventArgs e)
{
UserControl1.ButtonClicked += new EventHandler(UserControl1_ButtonClicked);
}
void UserControl1_ButtonClicked(object sender, EventArgs e)
{
}
As well as using the above approach you can also cast the Page reference in the UserControl and call a public method directly:
MyPage page = (MyPage)Page;
page.AMethod();
Hope this helps.

Categories