In one of my previous blog posts I have explained how to display hierarchical data with Row Details. Now, if you are familiar with Row Details features, you know that you are not limited to showing the details inside RadGridView. You can show them anywhere by using the handy external DetailsPresenter. As a matter of fact, each GridViewRow has one of those DetailsPresenter’s inside its template. So you will be using the same class that we are using internally to show the details of each single row.
The documentation states that in order to display Row Details outside RadGridView, you need to place a DetailsPresenter control somewhere around RadGridView and wire them up. Well, it does not need to be around, really. Let’s place it in Telerik’s RadWindow:
1: public MainPage()
2: {
3: InitializeComponent();
4:
5: this.DataContext = new FootballViewModel();
6:
7: this.window = new RadWindow();
8: this.window.Content = new DetailsPresenter()
9: {
10: // Link the external details presenter to our RadGridView.
11: DetailsProvider = this.clubsGrid.RowDetailsProvider
12: };
13: this.window.WindowStartupLocation = WindowStartupLocation.Manual;
14: this.window.Header = "Players";
15: this.window.ResizeMode = ResizeMode.NoResize;
16: this.clubsGrid.RowDetailsProvider.PropertyChanged += this.OnRowDetailsProviderPropertyChanged;
17: }
The DetailsPresenter cares about three things – what is the DataTemplate it needs to load, whether it is visible or not, and what is its DataContext. All this information comes through its DetailsProvider property which is assigned from RadGridView’s respective property RowDetailsProvider. This means that this particular DetailsPresenter will be fed by this particular RadGridView. Let’s take a look at the interface:
1: public interface IDetailsProvider : INotifyPropertyChanged
2: {
3: DataTemplate Template { get; }
4: Visibility Visibility { get; }
5: object DataContext { get; }
6: //Rest of the code is omitted
7: }
In case you have not noticed, it inherits from the INotifyPropertyChanged interface. Each time a row is selected in RadGridView, the DataContext of the DetailsProvider changes. The DetailsPresenter listens for these property changes and updates as needed. We can listen for a PropertyChanged ourselves and position the window accordingly:
1: private void OnRowDetailsProviderPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
2: {
3: if (e.PropertyName == "DataContext")
4: {
5: // This indicates that selection has changed in RadGridView.
6: Club currentClub = this.clubsGrid.RowDetailsProvider.DataContext as Club;
7: if (currentClub != null)
8: {
9: // A row is selected.
10: var row = this.clubsGrid.ItemContainerGenerator.ContainerFromItem(currentClub) as GridViewRow;
11: Point newLocation = this.CalculateWindowLocation(row);
12:
13: // Show the window next to the row on the right
14: this.window.Left = newLocation.X;
15: this.window.Top = newLocation.Y;
16:
17: this.window.Show();
18: }
19: else
20: {
21: // There is no selection.
22: this.window.Hide();
23: }
24: }
25: }
That’s about all you need to do. Below you can see the RadGridView+RadWindow combo in action. Fell free to play with the window. When you select another row it will be brought back to where it belongs. Ctrl-click a selected row to deselect it and the window will disappear.
You can find the full source code here.