This is a migrated thread and some comments may be shown as answers.

Expand/collapse all in ControlTemplate

10 Answers 80 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Håkan
Top achievements
Rank 1
Håkan asked on 28 Mar 2012, 03:20 PM
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

10 Answers, 1 is accepted

Sort by
0
Pavel Pavlov
Telerik team
answered on 29 Mar 2012, 09:49 AM
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 >>
0
Håkan
Top achievements
Rank 1
answered on 30 Mar 2012, 07:19 AM
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


0
Pavel Pavlov
Telerik team
answered on 03 Apr 2012, 04:29 PM
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 >>
0
Håkan
Top achievements
Rank 1
answered on 04 Apr 2012, 07:49 AM
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
0
Pavel Pavlov
Telerik team
answered on 05 Apr 2012, 09:14 AM
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 >>

0
Håkan
Top achievements
Rank 1
answered on 05 Apr 2012, 09:34 AM
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
0
Pavel Pavlov
Telerik team
answered on 05 Apr 2012, 09:57 AM
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 >>

0
Håkan
Top achievements
Rank 1
answered on 05 Apr 2012, 10:12 AM
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
0
Accepted
Pavel Pavlov
Telerik team
answered on 05 Apr 2012, 11:19 AM
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 >>

0
Håkan
Top achievements
Rank 1
answered on 05 Apr 2012, 08:58 PM
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
Tags
GridView
Asked by
Håkan
Top achievements
Rank 1
Answers by
Pavel Pavlov
Telerik team
Håkan
Top achievements
Rank 1
Share this question
or