Expand/collapse all in ControlTemplate

11 posts, 1 answers
  1. Håkan
    Håkan avatar
    183 posts
    Member since:
    May 2011

    Posted 28 Mar 2012 Link to this post

    Hi,

    I'm trying to implement the ExpandAllGroups() / CollapseAllGroups() functionality with a ToggleButton inside the GridView.
    I have modified the ControlTemplate for the GridViewHeaderIndentCell and placed a ToggleButton there.
    I have also managed to implement the graphics for it (I use the same arrow as in the GridViewGroupRowTemplate) and it rotates 180 degrees when toggled. (See attached image).
    But how can I get an event from it so I can call the ExpandAllGroups() / CollapseAllGroups() methods?
    Or can I connect a command to it somehow?

    I have my own implementation of the grid that inherits from RadGridView if that would make it easier?
    I can't add a click event in the template because it the template is in a separate resourcefile with no code behind.

    I tried to find the button in OnApplyTemplate() using GetTemplateChild() but it does not exist at that moment, not until the data is loaded and grouped.

    Here is my template:

    <ControlTemplate TargetType="telerik:GridViewHeaderIndentCell">
                      <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Width="25">
                          <ToggleButton x:Name="ExpandAllButton" Width="20" Height="20" Margin="0" VerticalAlignment="Center" HorizontalAlignment="Center">
                              <ToggleButton.Template>
                                  <ControlTemplate TargetType="ToggleButton">
                                      <Grid>
                                          <VisualStateManager.VisualStateGroups>
                                              <VisualStateGroup x:Name="CommonStates">
                                                  <VisualState x:Name="Normal"/>
                                                  <VisualState x:Name="MouseOver"/>
                                                  <VisualState x:Name="Pressed"/>
                                                  <VisualState x:Name="Disabled" />
                                              </VisualStateGroup>
                                              <VisualStateGroup x:Name="CheckStates">
                                                  <VisualState x:Name="Checked">
                                                      <Storyboard>
                                                          <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" Storyboard.TargetName="Arrow">
                                                              <EasingDoubleKeyFrame KeyTime="00:00:00.2" Value="180"/>
                                                          </DoubleAnimationUsingKeyFrames>
                                                      </Storyboard>
                                                  </VisualState>
                                                  <VisualState x:Name="Unchecked">
                                                      <Storyboard>
                                                          <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" Storyboard.TargetName="Arrow">
                                                              <EasingDoubleKeyFrame KeyTime="00:00:00.2" Value="0"/>
                                                          </DoubleAnimationUsingKeyFrames>
                                                      </Storyboard>
                                                  </VisualState>
                                              </VisualStateGroup>
                                              <VisualStateGroup x:Name="FocusStates">
                                                  <VisualState x:Name="Focused"/>
                                                  <VisualState x:Name="Unfocused"/>
                                              </VisualStateGroup>
                                          </VisualStateManager.VisualStateGroups>
                                          <Path x:Name="Arrow" Data="M0,0L1,0 2,0 2,0.99999991 3,0.99999991 3,2 4,2 4,0.99999991 5,0.99999991 5,0 5.9999999,0 7,0 7,0.99999991 5.9999999,0.99999991 5.9999999,2 5,2 5,3 4,3 4,4 3,4 3,3 2,3 2,2 1,2 1,0.99999991 0,0.99999991z" Fill="Black" Height="5" Width="7" Margin="5" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center" VerticalAlignment="Center">
                                              <Path.RenderTransform>
                                                  <RotateTransform />
                                              </Path.RenderTransform>
                                          </Path>
                                      </Grid>
                                  </ControlTemplate>
                              </ToggleButton.Template>
                          </ToggleButton>
                      </Border>
                  </ControlTemplate>

    Regards,
    Håkan

  2. Pavel Pavlov
    Admin
    Pavel Pavlov avatar
    2039 posts

    Posted 29 Mar 2012 Link to this post

    Hello,

    You can get reference to your button using the ChildrenOfType<> extension method (using Telerik.Windows.Controls)  inside the handler of the Grouped event of RadGridView .

    Hope that helps.

    All the best,
    Pavel Pavlov
    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. Håkan
    Håkan avatar
    183 posts
    Member since:
    May 2011

    Posted 30 Mar 2012 Link to this post

    Hi,

    I can't get it to work.
    The GetChildrenOfType<> method will not find my ToggleButton.
    I also tried to take it one step at a time from the IndentPresenter digging further down, but when I get to the StackPanel inside the ItemsPresenter it has no children at this point.

    See attached image for a screen shot of Silverlight Spy that I used to identify all components.

    Here is my code:
    private void DataGrid_Grouped(object sender, GridViewGroupedEventArgs e)
            {
                foreach (IndentPresenter indent in DataGrid.ChildrenOfType<IndentPresenter>())
                {
                    foreach (ItemsPresenter items in indent.ChildrenOfType<ItemsPresenter>())
                    {
                        foreach (StackPanel panel in items.ChildrenOfType<StackPanel>())
                        {
                            foreach (ContentPresenter content in panel.ChildrenOfType<ContentPresenter>())
                            {
                                foreach (GridViewHeaderIndentCell cell in content.ChildrenOfType<GridViewHeaderIndentCell>())
                                {
                                    foreach (ToggleButton btn in cell.ChildrenOfType<ToggleButton>())
                                    {
                                        if (btn.Name == "ExpandAllButton")
                                            btn.Click += new RoutedEventHandler(ExpandAllButton_Click);
                                    }
                                }
                            }
                        }
                    }
                }
            }

    Isn't there any better way to do this?

    Another problem I have is that I have a predefined grouping on one column. Then the Grouped event will not be triggered.
    It only triggers if i manually add another group.

    Regards,
    Håkan


  5. Pavel Pavlov
    Admin
    Pavel Pavlov avatar
    2039 posts

    Posted 03 Apr 2012 Link to this post

    Hi,

    Actually I believe there is a better approach:

    The checked event of the toggle button event is a Routed event .
    So you can subscribe to it as follows :

    this.AddHandler(ToggleButton.CheckedEvent, new RoutedEventHandler(this.t_Checked));
    void t_Checked(object sender, RoutedEventArgs e)
    {
            //do expand/collapse RadGridview here.

    }
    All the best,
    Pavel Pavlov
    the Telerik team
    Sharpen your .NET Ninja skills! Attend Q1 webinar week and get a chance to win a license! Book your seat now >>
  6. Håkan
    Håkan avatar
    183 posts
    Member since:
    May 2011

    Posted 04 Apr 2012 Link to this post

    Hi Pavel,

    My problem is how I can get a hold of the button to add an event to it, since the button is located in the GridViewHeaderIndentCell control template.

    Regards,
    Håkan
  7. Pavel Pavlov
    Admin
    Pavel Pavlov avatar
    2039 posts

    Posted 05 Apr 2012 Link to this post

    Hello Hakan,

    Exactly! My last code demonstrates how to  subscribe to the event of the button without having to find it.
    I have tried it and it worked ok. The idea is that the routed event bubbles up the visual tree and you can handle it without having to find the button previously.

    In case you have difficulties to adapt this approach to your scenario -- just send me a small runnable project and I would gladly implement it there  for you.

    Greetings,
    Pavel Pavlov
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  8. Håkan
    Håkan avatar
    183 posts
    Member since:
    May 2011

    Posted 05 Apr 2012 Link to this post

    OK, now I understand what you mean, sorry...

    But ToggleButton.CheckedEvent gives me the compile error:
    'System.Windows.Controls.Primitived.ToggleButton' does not contain a definition for 'CheckedEvent'.

    - Håkan
  9. Pavel Pavlov
    Admin
    Pavel Pavlov avatar
    2039 posts

    Posted 05 Apr 2012 Link to this post

    Hi ,

    Please receive my apologies. It seems I was doing it on a WPF project rather than Silverlight.
    In Silverlight we still have a chance. I have prepared a small runnable demo for you . It demonstrates handling the toggle button without having to get a reference to it initially.
    Please find the project attached.

    Greetings,
    Pavel Pavlov
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  10. Håkan
    Håkan avatar
    183 posts
    Member since:
    May 2011

    Posted 05 Apr 2012 Link to this post

    Thanks for the quick reply.

    Now I start to get somewhere, but I also need to pass the button in the event somehow.
    Because I need to get the state of the button (Checked or not).

    It would be nice if "sender" in the event was the button, but how do I pass it in:
    this.AddHandler(ToggleButton.MouseLeftButtonUpEvent, new MouseButtonEventHandler(this.b_MouseLeftButtonUp), true);
    

    I would like to do something like this in the eventhandler:
    private void ToggleButton_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
           {
               ToggleButton btn = sender as ToggleButton;
     
               if (btn != null && btn.Name == "ExpandAllButton")
               {
                   if (btn.IsChecked == true)
                       DataGrid.ExpandAllGroups();
                   else
                       DataGrid.CollapseAllGroups();
               }
           }


    Regards,
    Håkan
  11. Answer
    Pavel Pavlov
    Admin
    Pavel Pavlov avatar
    2039 posts

    Posted 05 Apr 2012 Link to this post

    Hi,

    We need some magic with the e.OriginalSource here. Demonstrated in the project attached.

    Kind regards,
    Pavel Pavlov
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  12. Håkan
    Håkan avatar
    183 posts
    Member since:
    May 2011

    Posted 05 Apr 2012 Link to this post

    Thanks Pavel!

    Now I got it working.

    My only problem now is that since I added the button to the HeaderIndentCell, I get one button for each group level I add.
    But I guess thats a minor problem I can live with.
    I can't seem to get the group level, otherwise I could maybe bind the visibility property to that.

    Regards,
    Håkan
Back to Top
DevCraft banner