What happens to Tab Headers when a pane is floated.

4 posts, 0 answers
  1. Tayllor
    Tayllor avatar
    13 posts
    Member since:
    Mar 2012

    Posted 09 Mar 2012 Link to this post

    Hello,

    When a radpane is undocked into a floating state.  What happens to the Header?  Which leads to the next question, how is the header then loaded back when the pane is transitioned back from floating to docked?

    In the context of what I'm trying to do...
    I have added a custom close button to my dynamically generated radpane (I need to do additional bookkeeping when the tab is closed).  When the pane is loaded, I would wire up the click handler and remove the loaded handler.  However, after I float the pane and then re-dock the pane, the click handler for the button is no longer available.  
    In the end, I do not remove the loaded handler, and I have to rewire the click event handler when the loaded event fires after docking.

    Is there a more elegant way of achieving the desired outcome of only having to attach the click handler once?
  2. Georgi
    Admin
    Georgi avatar
    349 posts

    Posted 15 Mar 2012 Link to this post

    Hi Tayllor,

    The pane changes its visual tree when it is undocked, but the header is moved to the new visual tree too. There is no template for the header in the new visual tree and that is why it does not look the same way as in dock state. So when you dock it back in the old tree it is shown again.

    In the attached simple project you can see what I have tried to reproduce the problem, but with no luck.
    Can you tell me if we are doing something different?
    Also what you can try to do is to set DataContext, for example like this:
    Header = "{Binding DataContext.SelectedCase, ElementName=dock, Mode= TwoWay}"

    Greetings,
    Georgi
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
  3. DevCraft banner
  4. Tayllor
    Tayllor avatar
    13 posts
    Member since:
    Mar 2012

    Posted 15 Mar 2012 Link to this post

    Hi Georgi,

    Thank you for the sample project, it does give some guidance for a work around.

    As far as reproducing the problem, I made some changes that 1) more closely simulate what I am trying to do and 2) give some debug capabilities / statements while running to the program.  I probably was vague in my initial description, but the click handler for the button is wired up at runtime by adding to the button.Click event.  This button wiring seems to be lost during dock / float transitions.

    First change to the XAML
    1) Added a loaded event listener for the pane 1 loaded.
    2) Added a checkbox to determine if the user wants to wire up the click handler whenever the Pane_Loaded event.  
    3) Added a textbox to change the text as the program runs (debug statements).
    <UserControl x:Class="CustomCloseButton_SL.MainPage"
            mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
        <UserControl.Resources>
            <DataTemplate x:Key="TitleTemplate">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" />
                        <ColumnDefinition />
                    </Grid.ColumnDefinitions>
                    <ContentPresenter Content="{Binding}"
                              Margin="0,0,75,0" />
                    <telerik:RadButton Grid.Column="1" x:Name="CloseButton"
                               Content="CustomButton" Visibility="Visible"/>
                </Grid>
            </DataTemplate>
        </UserControl.Resources>
        <Grid x:Name="LayoutRoot" Margin="5">
            <Grid.RowDefinitions>
                <RowDefinition Height="30"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <CheckBox Name="cbFireLoadedEverytime" Content="Wire Click Handler on every Pane_Loaded call?" />
            <telerik:RadDocking Grid.Row="1">
                <telerik:RadSplitContainer>
                    <telerik:RadPaneGroup>
                        <telerik:RadPane  x:Name="pane" Loaded="pane_Loaded"  HeaderTemplate="{StaticResource TitleTemplate}"  TitleTemplate="{StaticResource TitleTemplate}">
                            <StackPanel>
                                <TextBlock Text="Pame with close button"/>
                                <TextBlock Name="Feedback" />
                            </StackPanel>
                        </telerik:RadPane>
                    </telerik:RadPaneGroup>
                    <telerik:RadPaneGroup>
                        <telerik:RadPane Header="Pane 2">
                        </telerik:RadPane>
                    </telerik:RadPaneGroup>
                </telerik:RadSplitContainer>
            </telerik:RadDocking>
        </Grid>
    </UserControl>

    Then the code behind file..
    1) Added a FindChild method for a basic visual tree traversal to find the button.
    2) Added the event listener for RadPane Loaded event.
    3) Added some debug statements.
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Media;
     
    namespace CustomCloseButton_SL
    {
        public partial class MainPage : UserControl
        {
            public MainPage()
            {
                InitializeComponent();
            }
     
            private void CloseButton_Click(object sender, RoutedEventArgs e)
            {
                MessageBox.Show("Click Event");
            }
     
            private void pane_Loaded(object sender, RoutedEventArgs e)
            {
                // only want to stitch this up once
                Telerik.Windows.Controls.RadPane pane = sender as Telerik.Windows.Controls.RadPane;
     
                if ((bool)cbFireLoadedEverytime.IsChecked)
                {
                    // find the button and attach the listener
                    var buttonQuery = FindChild(pane, typeof(Telerik.Windows.Controls.RadButton), "CloseButton");
                    var button = buttonQuery as Telerik.Windows.Controls.RadButton;
                    if (null != button)
                    {
                        button.Click += new RoutedEventHandler(CloseButton_Click);
                        Feedback.Text = "pane loaded: Attached Button Handler";
                    }
                    else
                    {
                        Feedback.Text = "pane loaded: could not find button";
                    }
                }
                else
                {
                    Feedback.Text = "pane loaded: click event will not be wired up";
                }
            }
     
            /// <summary>
            /// Quick Find Child (may not be 100%)
            /// </summary>
            private DependencyObject FindChild(DependencyObject parent, System.Type type, string childName)
            {
                if (parent == null) return null;
     
                DependencyObject foundChild = null;
     
                int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
                for (int i = 0; i < childrenCount; i++)
                {
                    var child = VisualTreeHelper.GetChild(parent, i);
                    if (child.GetType() != type)
                    {
                        foundChild = FindChild(child, type, childName);
     
                        if (foundChild != null) break;
                    }
                    else if (!string.IsNullOrEmpty(childName))
                    {
                        var frameworkElement = child as FrameworkElement;
                        if (frameworkElement != null && frameworkElement.Name == childName)
                        {
                            foundChild = child;
                            break;
                        }
                    }
                    else
                    {
                        foundChild = child;
                        break;
                    }
                }
     
                return foundChild;
            }
        }
    }

    Thank you for your time,
    Tayllor
  5. Georgi
    Admin
    Georgi avatar
    349 posts

    Posted 16 Mar 2012 Link to this post

    H Tayllor,

    I have reproduced the problem and I can see how sometimes the event is lost. So I can't see better work around then wiring on load, except maybe using commands instead of events.

    All the best,
    Georgi
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
Back to Top