Forum Xamarin.Forms

Accessing controls in a ControlTemplate when event fires from a control on the template?

I have a ControlTemplate that has a few controls on it. It has a Label, a Button, a Frame, and an AbsoluteLayout control. The frame has a swipe gesture to it. The code behind for these controls is obviously in the App.xaml.cs file. In that code, when an event fires like the button click or the swipe gesture, I can't find out how to access other controls in the control template. When the user swipes the content in the frame, i want to do a Translation on the AbsoluteLayout. I've named the AbsoluteLayout, but I don't know how to get to it. By default, in event code, you can't use the name to access the other controls. For example, I can't seem to set the label text in the button click event by using the label's x:Name. What am I doing wrong? I tried using the App.Resources["Name"] but that doesn't seem to give me what I need. Any help would be greatly appreciated.

Best Answer

  • jonebersolejonebersole ✭✭
    Accepted Answer

    I was able to eventually figure out how to access other controls on the same ControlTemplate. I don't think it is the most elegant of solutions, but it does the job nicely for my situation. I broke out all of the statements individually so others could bend the solution to their will based on their situation.

    My AbsoluteLayout is the parent control to all of the controls that events fire within the ControlTemplate. This is how I am able to traverse up the Parent tree to eventually get to the AbsoluteLayout. At any point in the code below, you could substitute your control type or Parent that you are looking for. Theoretically, you could just get the top level parent and then use FindByName from that point too.

    Here is a common function I made to return the AbsoluteLayout that I need for my translation.

                private AbsoluteLayout GetBottomMenu(object sender)
                {
                    try
                    {
                        if (sender != null)
                        {
                            if (sender.GetType() == typeof(Frame))
                            {
                                Frame frame = (Frame)sender;
                                if (frame.Parent != null)
                                {
                                    if (frame.Parent.GetType() == typeof(StackLayout))
                                    {
                                        StackLayout stackLayout = (StackLayout)frame.Parent;
                                        if (stackLayout.Parent != null)
                                        {
                                            AbsoluteLayout absoluteLayout = (AbsoluteLayout)stackLayout.Parent;
                                            return absoluteLayout;
                                        }
                                    }
                                }
                            }
    
                        }
                    }
                    catch (Exception ex)
                    {
                        return null;
                    }
                    return null;
                }
    

    Then, in the gesture swipe events, I simply call...

    AbsoluteLayout absoluteLayout = GetBottomMenu(sender);

    Here is the full event for the gestures as reference.

            private async void BottomMenuSwipeUp_Swiped(object sender, SwipedEventArgs e)
            {
                try
                {
                    AbsoluteLayout absoluteLayout = GetBottomMenu(sender);
                    if (absoluteLayout != null)
                        await absoluteLayout.TranslateTo(0, 0, 1000, Easing.Linear);
                }
                catch (Exception ex)
                {
    
                }
            }
    
            private async void BottomMenuSwipeDown_Swiped(object sender, SwipedEventArgs e)
            {
                try
                {
                    RaffleBuddyCore.Modules.Notification.Current.NewNotifications = false;
                    AbsoluteLayout absoluteLayout = GetBottomMenu(sender);
                    if (absoluteLayout != null)
                        await absoluteLayout.TranslateTo(0, 300, 1000, Easing.Linear);
                }
                catch (Exception ex)
                {
    
                }
            }
    

Answers

  • jonebersolejonebersole Member ✭✭
    Accepted Answer

    I was able to eventually figure out how to access other controls on the same ControlTemplate. I don't think it is the most elegant of solutions, but it does the job nicely for my situation. I broke out all of the statements individually so others could bend the solution to their will based on their situation.

    My AbsoluteLayout is the parent control to all of the controls that events fire within the ControlTemplate. This is how I am able to traverse up the Parent tree to eventually get to the AbsoluteLayout. At any point in the code below, you could substitute your control type or Parent that you are looking for. Theoretically, you could just get the top level parent and then use FindByName from that point too.

    Here is a common function I made to return the AbsoluteLayout that I need for my translation.

                private AbsoluteLayout GetBottomMenu(object sender)
                {
                    try
                    {
                        if (sender != null)
                        {
                            if (sender.GetType() == typeof(Frame))
                            {
                                Frame frame = (Frame)sender;
                                if (frame.Parent != null)
                                {
                                    if (frame.Parent.GetType() == typeof(StackLayout))
                                    {
                                        StackLayout stackLayout = (StackLayout)frame.Parent;
                                        if (stackLayout.Parent != null)
                                        {
                                            AbsoluteLayout absoluteLayout = (AbsoluteLayout)stackLayout.Parent;
                                            return absoluteLayout;
                                        }
                                    }
                                }
                            }
    
                        }
                    }
                    catch (Exception ex)
                    {
                        return null;
                    }
                    return null;
                }
    

    Then, in the gesture swipe events, I simply call...

    AbsoluteLayout absoluteLayout = GetBottomMenu(sender);

    Here is the full event for the gestures as reference.

            private async void BottomMenuSwipeUp_Swiped(object sender, SwipedEventArgs e)
            {
                try
                {
                    AbsoluteLayout absoluteLayout = GetBottomMenu(sender);
                    if (absoluteLayout != null)
                        await absoluteLayout.TranslateTo(0, 0, 1000, Easing.Linear);
                }
                catch (Exception ex)
                {
    
                }
            }
    
            private async void BottomMenuSwipeDown_Swiped(object sender, SwipedEventArgs e)
            {
                try
                {
                    RaffleBuddyCore.Modules.Notification.Current.NewNotifications = false;
                    AbsoluteLayout absoluteLayout = GetBottomMenu(sender);
                    if (absoluteLayout != null)
                        await absoluteLayout.TranslateTo(0, 300, 1000, Easing.Linear);
                }
                catch (Exception ex)
                {
    
                }
            }
    
Sign In or Register to comment.