Hi Hristo, thanx for coming back to me on this.
Right, I have been doing some further investigation into this and have now managed to fix many of the memory leaks I was suffereing from by using WinDbg and a lot of trial and error. A lot of the issue were linked to parent controls setting event handlers against child controls. There is one control left that I am unable to resolve and cannot see an obvious reason as to why the memory cannot be freed. The control is a RadWindow, which contains 2 RadGridView controls + 2 custom toolbar controls (the toolbar control is based on the XAML I posted earlier and can be used with any RadGridView). For some reason however the instance of the RadWindow can never be garbage collected. If I remove the 2 toolbars the instances are removed. I have the toolbar on other controls and these can be garbage collected without issue so there must be something in the setup of this control causing the issue.
If you could possibly have a quick look at the below details that would be very much appreciated:
XAML of RadWindow control (Note the 2 <local:GridViewToolbar controls that are causing the issue):
<
telerikSchema:RadWindow
x:Class
=
"Insurer.Analytics.SharedResources.Controls.ContentPickerControl"
xmlns:telerik
=
"clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView"
xmlns:CommonControls
=
"clr-namespace:Insurer.Analytics.Common.CommonControls;assembly=Insurer.Analytics.Common"
xmlns:Controls
=
"clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls"
xmlns:local
=
"clr-namespace:Insurer.Analytics.SharedResources.Controls"
CanMove
=
"False"
CanClose
=
"False"
Height
=
"750"
Width
=
"1150"
Header
=
"Add Content"
ResizeMode
=
"NoResize"
WindowStartupLocation
=
"CenterScreen"
mc:Ignorable
=
"d"
d:DesignHeight
=
"720"
d:DesignWidth
=
"620"
>
<
telerikSchema:RadWindow.Resources
>
<
ResourceDictionary
>
<
ResourceDictionary.MergedDictionaries
>
<
ResourceDictionary
Source
=
"/Insurer.Analytics.SharedResources;component/ResourceDictionary.xaml"
/>
<
ResourceDictionary
>
<
Controls:BooleanToVisibilityConverter
x:Key
=
"BoolToVisibilityConverter"
/>
</
ResourceDictionary
>
</
ResourceDictionary.MergedDictionaries
>
</
ResourceDictionary
>
</
telerikSchema:RadWindow.Resources
>
<
Grid
x:Name
=
"LayoutRoot"
Background
=
"{StaticResource LayoutRootBackground}"
>
<
telerikSchema:RadTabControl
>
<
telerikSchema:RadTabControl.Items
>
<
telerikSchema:RadTabItem
Header
=
"Published Content"
>
<
Grid
>
<
Grid.RowDefinitions
>
<
RowDefinition
Height
=
"Auto"
/>
<
RowDefinition
Height
=
"*"
/>
</
Grid.RowDefinitions
>
<
StackPanel
Orientation
=
"Vertical"
>
<
TextBlock
Text
=
"SELECT CONTENT ITEM"
FontWeight
=
"Bold"
Margin
=
"5"
/>
<
local:GridViewToolbar
x:Name
=
"PublicationToolbar"
Margin
=
"5,0,0,0"
/>
<
telerik:RadGridView
x:Name
=
"PublicationGrid"
RowIndicatorVisibility
=
"Collapsed"
ColumnWidth
=
"*"
ItemsSource
=
"{Binding Publications}"
SelectedItem
=
"{Binding SelectedPublication, Mode=TwoWay}"
EnableColumnVirtualization
=
"True"
EnableRowVirtualization
=
"True"
RowLoaded
=
"Grid_RowLoaded"
DataLoaded
=
"PublicationGrid_DataLoaded"
Margin
=
"5"
MaxHeight
=
"260"
AutoGenerateColumns
=
"False"
SelectionChanged
=
"RadGridView_SelectionChanged"
>
<
telerik:RadGridView.Columns
>
<
telerik:GridViewDataColumn
Header
=
"Publication Name"
MinWidth
=
"200"
DataMemberBinding
=
"{Binding PublicationName}"
ToolTipService.ToolTip
=
"{Binding Name}"
ShowDistinctFilters
=
"False"
MaxWidth
=
"500"
/>
<
telerik:GridViewDataColumn
Header
=
"Type"
MinWidth
=
"80"
DataMemberBinding
=
"{Binding ItemType}"
ToolTipService.ToolTip
=
"{Binding ItemType}"
ShowDistinctFilters
=
"True"
MaxWidth
=
"200"
/>
<
telerik:GridViewDataColumn
Header
=
"Category"
MinWidth
=
"80"
DataMemberBinding
=
"{Binding CategoryName}"
ToolTipService.ToolTip
=
"{Binding CategoryName}"
ShowDistinctFilters
=
"True"
MaxWidth
=
"200"
/>
<
telerik:GridViewDataColumn
Header
=
"Last Updated"
MinWidth
=
"150"
DataMemberBinding
=
"{Binding UpdatedDate}"
IsResizable
=
"False"
Width
=
"150"
IsFilterable
=
"False"
/>
<
telerik:GridViewDataColumn
Header
=
"Description"
MinWidth
=
"150"
DataMemberBinding
=
"{Binding PublicationDescription}"
ToolTipService.ToolTip
=
"{Binding Description}"
ShowDistinctFilters
=
"False"
/>
</
telerik:RadGridView.Columns
>
</
telerik:RadGridView
>
<
CheckBox
Margin
=
"5"
x:Name
=
"ShowInstanceGrid"
Content
=
"Choose Specific Instance"
IsChecked
=
"False"
HorizontalAlignment
=
"Left"
Checked
=
"ShowInstanceGrid_Checked"
Unchecked
=
"ShowInstanceGrid_Unchecked"
/>
<
StackPanel
x:Name
=
"InstanceDetails"
Orientation
=
"Vertical"
Visibility
=
"{Binding ElementName=ShowInstanceGrid, Path=IsChecked, Converter={StaticResource BoolToVisibilityConverter}}"
>
<
TextBlock
Text
=
"SELECT SPECIFIC INSTANCE"
FontWeight
=
"Bold"
Margin
=
"5"
/>
<
local:GridViewToolbar
x:Name
=
"InstanceToolbar"
Margin
=
"5,0,0,0"
/>
<
telerik:RadGridView
x:Name
=
"InstanceGrid"
RowIndicatorVisibility
=
"Collapsed"
Margin
=
"5"
RowLoaded
=
"Grid_RowLoaded"
ItemsSource
=
"{Binding SelectedPublication.Instances}"
SelectedItem
=
"{Binding SelectedInstance, Mode=TwoWay}"
MaxHeight
=
"235"
AutoGenerateColumns
=
"False"
ColumnWidth
=
"*"
>
<
telerik:RadGridView.Columns
>
<
telerik:GridViewDataColumn
Header
=
"Name"
MinWidth
=
"200"
DataMemberBinding
=
"{Binding Name}"
ToolTipService.ToolTip
=
"{Binding Name}"
ShowDistinctFilters
=
"False"
MaxWidth
=
"500"
/>
<
telerik:GridViewDataColumn
Header
=
"Published Date"
SortMemberPath
=
"PublishedDate"
DataMemberBinding
=
"{Binding PublishedDate}"
MinWidth
=
"150"
Width
=
"150"
IsResizable
=
"False"
ShowDistinctFilters
=
"False"
>
<
telerik:GridViewDataColumn.FilteringControl
>
<
CommonControls:DateRangeFilterControl
/>
</
telerik:GridViewDataColumn.FilteringControl
>
</
telerik:GridViewDataColumn
>
<
telerik:GridViewDataColumn
Header
=
"Description"
MinWidth
=
"250"
DataMemberBinding
=
"{Binding Description}"
ToolTipService.ToolTip
=
"{Binding Description}"
ShowDistinctFilters
=
"False"
/>
</
telerik:RadGridView.Columns
>
</
telerik:RadGridView
>
</
StackPanel
>
</
StackPanel
>
<
Grid
VerticalAlignment
=
"Bottom"
Grid.Row
=
"1"
>
<
telerikSchema:RadButton
Content
=
"Preview"
Click
=
"PreviewButtonClick"
HorizontalAlignment
=
"Left"
Width
=
"100"
Margin
=
"5,8,0,8"
/>
<
StackPanel
Orientation
=
"Horizontal"
HorizontalAlignment
=
"Center"
Margin
=
"8"
>
<
telerikSchema:RadButton
x:Name
=
"btnOK"
Content
=
"OK"
Click
=
"btnOK_Click"
Width
=
"100"
Margin
=
"0 0 5 0"
/>
<
telerikSchema:RadButton
x:Name
=
"btnCancel"
Content
=
"{Binding Path=StringResources.Cancel, Source={StaticResource LocalizedResources }}"
Click
=
"btnCancel_Click"
Width
=
"100"
/>
</
StackPanel
>
</
Grid
>
</
Grid
>
</
telerikSchema:RadTabItem
>
<
telerikSchema:RadTabItem
x:Name
=
"TabKPISummary"
Header
=
"Custom Content"
>
<
Grid
>
<
Grid.RowDefinitions
>
<
RowDefinition
Height
=
"Auto"
/>
<
RowDefinition
Height
=
"*"
/>
</
Grid.RowDefinitions
>
<
local:KPISummarySettingsControl
x:Name
=
"kpiSummarySettings"
DataContext
=
"{Binding KPISummaryViewModel}"
Grid.Row
=
"0"
/>
<
StackPanel
Orientation
=
"Horizontal"
HorizontalAlignment
=
"Center"
VerticalAlignment
=
"Bottom"
Margin
=
"8"
Grid.Row
=
"1"
>
<
telerikSchema:RadButton
x:Name
=
"btnKPISummaryOK"
Content
=
"OK"
Click
=
"btnKPISummaryOK_Click"
Width
=
"100"
Margin
=
"0 0 5 0"
/>
<
telerikSchema:RadButton
Content
=
"{Binding Path=StringResources.Cancel, Source={StaticResource LocalizedResources }}"
Click
=
"btnCancel_Click"
Width
=
"100"
/>
</
StackPanel
>
</
Grid
>
</
telerikSchema:RadTabItem
>
</
telerikSchema:RadTabControl.Items
>
</
telerikSchema:RadTabControl
>
</
Grid
>
</
telerikSchema:RadWindow
>
Code-behind for RadWindow control (With come implementation logic removed for brevity):
using
Business;
using
Business.ContentLoaders;
using
Business.Publication;
using
Business.ViewModels;
using
Business.ViewModel.Visualisations;
using
Insurer.Analytics.Common.Events;
using
Insurer.Analytics.Common.Formatting;
using
Insurer.Analytics.SharedResources.Behaviours;
using
Insurer.Analytics.SharedResources.ViewModels;
using
System;
using
System.Collections.Generic;
using
System.Diagnostics;
using
System.Globalization;
using
System.Linq;
using
System.Net;
using
System.Windows;
using
System.Windows.Controls;
using
System.Windows.Documents;
using
System.Windows.Input;
using
System.Windows.Markup;
using
System.Windows.Media;
using
System.Windows.Media.Animation;
using
System.Windows.Shapes;
using
Telerik.Windows.Controls;
using
WindowStartupLocation = Telerik.Windows.Controls.WindowStartupLocation;
namespace
Insurer.Analytics.SharedResources.Controls
{
public
partial
class
ContentPickerControl : RadWindow
{
private
ContentPickerViewModel _viewModel;
private
Mode _mode = Mode.Unknown;
public
ContentPickerControl(ContentPickerViewModel viewModel, Mode mode)
{
this
.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.Name);
InitializeComponent();
this
.PublicationToolbar.GridView =
this
.PublicationGrid;
this
.InstanceToolbar.GridView =
this
.InstanceGrid;
_viewModel = viewModel;
DataContext = _viewModel;
_viewModel.SelectedPublication = _viewModel.Publications.FirstOrDefault();
this
._mode = mode;
if
(_viewModel.IsKPISummary)
{
// We are editing an existing KPI summary so show correct tab
this
.TabKPISummary.IsSelected =
true
;
}
// Attach custom filtering behavior
this
.Loaded += (s, e) =>
{
BehaviorHelper.AttachFilterBehavior(
this
.PublicationGrid);
BehaviorHelper.AttachFilterBehavior(
this
.InstanceGrid);
};
this
.Closed += (o, e) =>
{
this
.DataContext =
null
;
_viewModel =
null
;
this
.PublicationToolbar.GridView =
null
;
this
.InstanceToolbar.GridView =
null
;
};
}
private
void
Grid_RowLoaded(
object
sender, Telerik.Windows.Controls.GridView.RowLoadedEventArgs e)
{
RadGridFormatting.AddStandardTooltips(e);
}
private
void
PublicationGrid_DataLoaded(
object
sender, EventArgs e)
{
this
.PublicationGrid.SelectedItem = _viewModel.Publications.FirstOrDefault();
}
public
void
ShowPreview()
{
if
(_viewModel.SelectedPublication ==
null
)
return
;
var instance = _viewModel.SelectedInstance ?? _viewModel.SelectedPublication.MostRecentInstance;
switch
(_viewModel.SelectedPublication.SourceItemTypeSUID)
{
case
Publication.PublicationType.CrossTab:
new
SnapshotContentLoader().LoadContent(instance.InstanceItemSUID, onComplete => ShowSnapshotPreview(onComplete.Result));
break
;
case
Publication.PublicationType.KPI:
new
KPIContentLoader().LoadContent(instance.InstanceItemSUID, onComplete => ShowKPIPreview(onComplete.Result));
break
;
default
:
return
;
}
}
private
void
ShowKPIPreview(KPIViewModel result)
{
var chart =
new
KPIViewerControl() { ViewMode = SnapshotViewMode.Chart, ViewModel = result, InlineViewModeEnabled =
true
};
chart.VisualisationSettings = VisualisationSettingsViewModel.DefaultVisualisationSettings();
var instance = _viewModel.SelectedInstance ?? _viewModel.SelectedPublication.MostRecentInstance;
var window = CreatePreviewWindow();
window.Content = chart;
window.Header =
"Preview - "
+ instance.Name;
window.Closed += (o, e) =>
{
chart.Unload();
};
window.ShowDialog();
}
private
void
ShowSnapshotPreview(SnapshotViewModel result)
{
var chart =
new
SnapshotViewerControl() { ViewMode = SnapshotViewMode.Chart, ViewModel = result, InlineViewModeEnabled =
true
};
chart.VisualisationSettings = VisualisationSettingsViewModel.DefaultVisualisationSettings();
var instance = _viewModel.SelectedInstance ?? _viewModel.SelectedPublication.MostRecentInstance;
var window = CreatePreviewWindow();
window.Content = chart;
window.Header =
"Preview - "
+ instance.Name;
window.Closed += (o, e) =>
{
chart.Unload();
};
window.ShowDialog();
}
private
RadWindow CreatePreviewWindow()
{
return
new
RadWindow()
{
ResizeMode = Telerik.Windows.Controls.ResizeMode.NoResize,
Width = 800,
Height = 550,
CanMove =
true
,
WindowStartupLocation = WindowStartupLocation.CenterScreen
};
}
private
void
PreviewButtonClick(
object
sender, RoutedEventArgs e)
{
ShowPreview();
}
private
void
btnOK_Click(
object
sender, RoutedEventArgs e)
{
if
(
this
._mode == Mode.Create)
{
CloseOK();
}
else
{
RadWindow.Confirm(
"Are you sure you want to overwrite the existing content?"
, (s, args) =>
{
if
(args.DialogResult.HasValue && args.DialogResult.Value)
CloseOK();
});
}
}
private
void
btnCancel_Click(
object
sender, RoutedEventArgs e)
{
Close();
}
private
void
CloseOK()
{
this
.DialogResult =
true
;
Close();
}
private
void
btnKPISummaryOK_Click(
object
sender, RoutedEventArgs e)
{
if
(
string
.IsNullOrEmpty(_viewModel.KPISummaryViewModel.Name) ||
string
.IsNullOrEmpty(_viewModel.KPISummaryViewModel.Description))
{
CommonEvents.ShowMessage(
"Name and Description are required."
);
return
;
}
if
(_viewModel.KPISummaryViewModel.SelectedContentType == KPIContentType.KPISummaryByCategory)
{
var count = _viewModel.KPISummaryViewModel.CategoryFilters.Select(f => f.IsSelected).Count();
var instances = _viewModel.KPISummaryViewModel.CategoryFilters.Select(f => f.IsSelected);
if
(_viewModel.KPISummaryViewModel.CategoryFilters.Where(f => f.IsSelected).Count() == 0)
{
CommonEvents.ShowMessage(
"Please select at least one Category"
);
return
;
}
}
else
{
if
(_viewModel.KPISummaryViewModel.KPIFilters.Where(f => f.IsSelected).Count() == 0)
{
CommonEvents.ShowMessage(
"Please select at least one KPI"
);
return
;
}
}
if
(_viewModel.KPISummaryViewModel.StatusFilters.Where(f => f.IsSelected).Count() == 0)
{
CommonEvents.ShowMessage(
"Please select at least one Status"
);
return
;
}
_viewModel.IsKPISummary =
true
;
if
(
this
._mode == Mode.Create)
{
CloseOK();
}
else
{
RadWindow.Confirm(
"Are you sure you want to overwrite current content?"
, (s, args) =>
{
if
(args.DialogResult.HasValue && args.DialogResult.Value)
CloseOK();
});
}
}
}
}
XAML of the GridViewToolbar control:
<
UserControl
x:Class
=
"Insurer.Analytics.SharedResources.Controls.GridViewToolbar"
xmlns:Controls2
=
"clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls"
xmlns:telerikRibbonBar
=
"clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.RibbonBar"
xmlns:grid
=
"clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.GridView"
xmlns:telerikNavigation
=
"clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Navigation"
xmlns:Controls
=
"clr-namespace:Telerik.Windows.Controls;assembly=Telerik.Windows.Controls.Charting"
xmlns:Telerik_Windows_Controls_RibbonBar_Primitives
=
"clr-namespace:Telerik.Windows.Controls.RibbonBar.Primitives;assembly=Telerik.Windows.Controls.RibbonBar"
xmlns:Converters
=
"clr-namespace:Insurer.Analytics.Common.Converters;assembly=Insurer.Analytics.Common"
xmlns:local
=
"clr-namespace:Insurer.Analytics.SharedResources.Controls"
mc:Ignorable
=
"d"
d:DesignHeight
=
"300"
d:DesignWidth
=
"400"
>
<
UserControl.Resources
>
<
ResourceDictionary
>
<
ResourceDictionary.MergedDictionaries
>
<
ResourceDictionary
Source
=
"/Insurer.Analytics.SharedResources;component/ResourceDictionary.xaml"
/>
</
ResourceDictionary.MergedDictionaries
>
</
ResourceDictionary
>
</
UserControl.Resources
>
<
Grid
x:Name
=
"LayoutRoot"
Background
=
"{StaticResource LayoutRootBackground}"
>
<
VisualStateManager.CustomVisualStateManager
>
<
ei:ExtendedVisualStateManager
/>
</
VisualStateManager.CustomVisualStateManager
>
<
VisualStateManager.VisualStateGroups
>
<
VisualStateGroup
x:Name
=
"ShowHideStates"
>
<
VisualState
x:Name
=
"Show"
>
<
Storyboard
>
<
DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty
=
"(UIElement.Opacity)"
Storyboard.TargetName
=
"ActionButtons"
d:IsOptimized
=
"True"
>
<
EasingDoubleKeyFrame
KeyTime
=
"0"
Value
=
"0.5"
/>
<
EasingDoubleKeyFrame
KeyTime
=
"0:0:0.3"
Value
=
"1"
/>
</
DoubleAnimationUsingKeyFrames
>
</
Storyboard
>
</
VisualState
>
<
VisualState
x:Name
=
"Hide"
>
<
Storyboard
>
<
DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty
=
"(UIElement.Opacity)"
Storyboard.TargetName
=
"ActionButtons"
d:IsOptimized
=
"True"
>
<
EasingDoubleKeyFrame
KeyTime
=
"0"
Value
=
"1"
/>
<
EasingDoubleKeyFrame
KeyTime
=
"0:0:0.3"
Value
=
"0.5"
/>
</
DoubleAnimationUsingKeyFrames
>
</
Storyboard
>
</
VisualState
>
</
VisualStateGroup
>
</
VisualStateManager.VisualStateGroups
>
<
telerik:RadButtonGroup
x:Name
=
"ActionButtons"
Margin
=
"0"
VerticalAlignment
=
"Top"
HorizontalAlignment
=
"Left"
Opacity
=
"0.5"
Height
=
"26"
>
<
i:Interaction.Triggers
>
<
i:EventTrigger
EventName
=
"MouseEnter"
>
<
ei:GoToStateAction
x:Name
=
"MouseEnterState"
StateName
=
"Show"
/>
</
i:EventTrigger
>
<
i:EventTrigger
EventName
=
"MouseLeave"
>
<
ei:GoToStateAction
x:Name
=
"MouseLeaveState"
StateName
=
"Hide"
/>
</
i:EventTrigger
>
</
i:Interaction.Triggers
>
<
telerik:RadRibbonDropDownButton
x:Name
=
"ddlExport"
Size
=
"Medium"
SmallImage
=
"/Insurer.Analytics.SharedResources;component/Icons/export1.png"
ToolTipService.ToolTip
=
"{Binding Path=StringResources.Export, Source={StaticResource LocalizedResources }}"
VerticalAlignment
=
"Center"
HorizontalAlignment
=
"Center"
Height
=
"25"
Width
=
"40"
>
<
telerik:RadRibbonDropDownButton.DropDownContent
>
<
telerikNavigation:RadContextMenu
>
<
local:KeyAwareMenuItem
Header
=
"{Binding Path=StringResources.ExportExcel, Source={StaticResource LocalizedResources }}"
IconTemplate
=
"{StaticResource MenuIcon}"
Icon
=
"/Insurer.Analytics.SharedResources;component/Icons/excel.png"
Command
=
"{Binding ExportCommand, Converter={StaticResource WeakCommandBindingConverter}}"
CommandParameter
=
"Excel"
/>
<
local:KeyAwareMenuItem
Header
=
"{Binding Path=StringResources.ExportCsv, Source={StaticResource LocalizedResources }}"
IconTemplate
=
"{StaticResource MenuIcon}"
Icon
=
"/Insurer.Analytics.SharedResources;component/Icons/csv.png"
Command
=
"{Binding ExportCommand, Converter={StaticResource WeakCommandBindingConverter}}"
CommandParameter
=
"CSV"
/>
</
telerikNavigation:RadContextMenu
>
</
telerik:RadRibbonDropDownButton.DropDownContent
>
</
telerik:RadRibbonDropDownButton
>
<
telerik:RadRibbonDropDownButton
x:Name
=
"ddlGridLines"
Size
=
"Medium"
SmallImage
=
"/Insurer.Analytics.SharedResources;component/Icons/table.png"
ToolTipService.ToolTip
=
"Gridlines"
VerticalAlignment
=
"Center"
HorizontalAlignment
=
"Center"
Height
=
"25"
Width
=
"40"
>
<
telerik:RadRibbonDropDownButton.DropDownContent
>
<
telerikNavigation:RadContextMenu
>
<
telerikNavigation:RadMenuItem
x:Name
=
"gridLinesBoth"
IsCheckable
=
"True"
IsChecked
=
"True"
Command
=
"{Binding GridLinesCommand, Converter={StaticResource WeakCommandBindingConverter}}"
CommandParameter
=
"Both"
>
<
telerikNavigation:RadMenuItem.Header
>
<
StackPanel
Orientation
=
"Horizontal"
>
<
Image
Source
=
"/Insurer.Analytics.SharedResources;component/Icons/table.png"
Margin
=
"0,0,5,0"
></
Image
>
<
TextBlock
Text
=
"{Binding Path=StringResources.Both, Source={StaticResource LocalizedResources }}"
></
TextBlock
>
</
StackPanel
>
</
telerikNavigation:RadMenuItem.Header
>
</
telerikNavigation:RadMenuItem
>
<
telerikNavigation:RadMenuItem
x:Name
=
"gridLinesHorizontal"
IsCheckable
=
"True"
Command
=
"{Binding GridLinesCommand, Converter={StaticResource WeakCommandBindingConverter}}"
CommandParameter
=
"Horizontal"
>
<
telerikNavigation:RadMenuItem.Header
>
<
StackPanel
Orientation
=
"Horizontal"
>
<
Image
Source
=
"/Insurer.Analytics.SharedResources;component/Icons/lines-horizontal.png"
Margin
=
"0,0,5,0"
></
Image
>
<
TextBlock
Text
=
"{Binding Path=StringResources.Horizontal, Source={StaticResource LocalizedResources }}"
></
TextBlock
>
</
StackPanel
>
</
telerikNavigation:RadMenuItem.Header
>
</
telerikNavigation:RadMenuItem
>
<
telerikNavigation:RadMenuItem
x:Name
=
"gridLinesVertical"
IsCheckable
=
"True"
Command
=
"{Binding GridLinesCommand, Converter={StaticResource WeakCommandBindingConverter}}"
CommandParameter
=
"Vertical"
>
<
telerikNavigation:RadMenuItem.Header
>
<
StackPanel
Orientation
=
"Horizontal"
>
<
Image
Source
=
"/Insurer.Analytics.SharedResources;component/Icons/lines-vertical.png"
Margin
=
"0,0,5,0"
></
Image
>
<
TextBlock
Text
=
"{Binding Path=StringResources.Vertical, Source={StaticResource LocalizedResources }}"
></
TextBlock
>
</
StackPanel
>
</
telerikNavigation:RadMenuItem.Header
>
</
telerikNavigation:RadMenuItem
>
<
telerikNavigation:RadMenuItem
x:Name
=
"gridLinesNone"
IsCheckable
=
"True"
Command
=
"{Binding GridLinesCommand, Converter={StaticResource WeakCommandBindingConverter}}"
CommandParameter
=
"None"
>
<
telerikNavigation:RadMenuItem.Header
>
<
StackPanel
Orientation
=
"Horizontal"
>
<
Image
Source
=
"/Insurer.Analytics.SharedResources;component/Icons/lines-none.png"
Margin
=
"0,0,5,0"
></
Image
>
<
TextBlock
Text
=
"{Binding Path=StringResources.None, Source={StaticResource LocalizedResources }}"
></
TextBlock
>
</
StackPanel
>
</
telerikNavigation:RadMenuItem.Header
>
</
telerikNavigation:RadMenuItem
>
</
telerikNavigation:RadContextMenu
>
</
telerik:RadRibbonDropDownButton.DropDownContent
>
</
telerik:RadRibbonDropDownButton
>
<
telerik:RadRibbonDropDownButton
x:Name
=
"ddlShow"
Size
=
"Medium"
SmallImage
=
"/Insurer.Analytics.SharedResources;component/Icons/preferences.png"
ToolTipService.ToolTip
=
"Show"
VerticalAlignment
=
"Center"
HorizontalAlignment
=
"Center"
Height
=
"25"
Width
=
"40"
>
<
telerik:RadRibbonDropDownButton.DropDownContent
>
<
telerikNavigation:RadContextMenu
>
<
telerikNavigation:RadMenuItem
x:Name
=
"filterToggle"
IsCheckable
=
"True"
IsChecked
=
"True"
Checked
=
"filterToggle_Checked"
Unchecked
=
"filterToggle_Unchecked"
>
<
telerikNavigation:RadMenuItem.Header
>
<
StackPanel
Orientation
=
"Horizontal"
>
<
Image
Source
=
"/Insurer.Analytics.SharedResources;component/Icons/funnel.png"
Margin
=
"0,0,5,0"
></
Image
>
<
TextBlock
Text
=
"Filters"
></
TextBlock
>
</
StackPanel
>
</
telerikNavigation:RadMenuItem.Header
>
</
telerikNavigation:RadMenuItem
>
<
telerikNavigation:RadMenuItem
x:Name
=
"groupingToggle"
IsCheckable
=
"True"
IsChecked
=
"False"
Checked
=
"groupingToggle_Checked"
Unchecked
=
"groupingToggle_Unchecked"
>
<
telerikNavigation:RadMenuItem.Header
>
<
StackPanel
Orientation
=
"Horizontal"
>
<
Image
Source
=
"/Insurer.Analytics.SharedResources;component/Icons/elements1.png"
Margin
=
"0,0,5,0"
></
Image
>
<
TextBlock
Text
=
"Grouping"
></
TextBlock
>
</
StackPanel
>
</
telerikNavigation:RadMenuItem.Header
>
</
telerikNavigation:RadMenuItem
>
</
telerikNavigation:RadContextMenu
>
</
telerik:RadRibbonDropDownButton.DropDownContent
>
</
telerik:RadRibbonDropDownButton
>
</
telerik:RadButtonGroup
>
</
Grid
>
</
UserControl
>
And finally code-behind for the Toolbar:
using
Business.ViewModel.Visualisations;
using
Insurer.Analytics.Common.Events;
using
Insurer.Analytics.Common.Export;
using
Insurer.Analytics.Common.Formatting;
using
Insurer.Analytics.SharedResources.Behaviours;
using
Microsoft.Practices.Composite.Presentation.Commands;
using
System;
using
System.Collections;
using
System.Globalization;
using
System.IO;
using
System.Windows;
using
System.Windows.Controls;
using
System.Windows.Input;
using
System.Windows.Markup;
using
System.Windows.Media;
using
Telerik.Data;
using
Telerik.Windows.Controls;
using
Telerik.Windows.Controls.GridView;
namespace
Insurer.Analytics.SharedResources.Controls
{
public
partial
class
GridViewToolbar : UserControl
{
private
GridElementExportingWeakEventSource _elementExporting;
#region Commands
private
readonly
ICommand _exportCommand;
private
readonly
ICommand _gridLinesCommand;
/// <summary>
/// Publicly exposed command to export current paged grid data.
/// </summary>
public
ICommand ExportCommand
{
get
{
return
_exportCommand; }
}
public
ICommand GridLinesCommand
{
get
{
return
_gridLinesCommand; }
}
#endregion
#region Public Properties
private
RadGridView _wrappedGridView;
public
RadGridView GridView
{
get
{
return
_wrappedGridView; }
set
{
_wrappedGridView = value;
if
(_wrappedGridView !=
null
)
{
InitialiseToolbarSettings();
}
}
}
public
WebPortalGridView WebPortalGridView
{
get
;
set
; }
#endregion
#region Constructor
public
GridViewToolbar()
{
this
.Language = XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.Name);
InitializeComponent();
// Setup wrapper for ElementExporting event of grid
_elementExporting =
new
GridElementExportingWeakEventSource();
_elementExporting.ElementExporting +=
new
EventHandler<GridViewElementExportingEventArgs>(GridView_ElementExporting);
// Commands to be exposed to the UI
_exportCommand =
new
DelegateCommand<
string
>(ExportGrid);
_gridLinesCommand =
new
DelegateCommand<
string
>(SetGridLines);
ActionButtons.DataContext =
this
;
}
#endregion
private
void
InitialiseToolbarSettings()
{
// Set up toolbar based on properties of current grid
this
.gridLinesBoth.IsChecked =
false
;
this
.gridLinesHorizontal.IsChecked =
false
;
this
.gridLinesVertical.IsChecked =
false
;
this
.gridLinesNone.IsChecked =
false
;
switch
(_wrappedGridView.GridLinesVisibility)
{
case
GridLinesVisibility.Both:
this
.gridLinesBoth.IsChecked =
true
;
break
;
case
GridLinesVisibility.Horizontal:
this
.gridLinesHorizontal.IsChecked =
true
;
break
;
case
GridLinesVisibility.Vertical:
this
.gridLinesVertical.IsChecked =
true
;
break
;
default
:
this
.gridLinesNone.IsChecked =
true
;
break
;
}
this
.filterToggle.IsChecked = _wrappedGridView.IsFilteringAllowed;
this
.groupingToggle.IsChecked = _wrappedGridView.ShowGroupPanel;
_elementExporting.SetEventSource(_wrappedGridView);
}
void
GridView_ElementExporting(
object
sender, GridViewElementExportingEventArgs e)
{
RadGridFormatting.FormatElementOnExport(e);
}
/// <summary>
/// Exports the current page of grid data in the required format.
/// Exported document is persisted to users file system via a save file dialog.
/// </summary>
/// <param name="format">User selected export format.</param>
private
void
ExportGrid(
string
format)
{
if
(_wrappedGridView ==
null
)
return
;
string
extension =
""
;
ExportFormat format1 = ExportFormat.Html;
switch
(format)
{
case
"Excel"
:
extension =
"xls"
;
format1 = ExportFormat.Html;
break
;
case
"ExcelML"
:
extension =
"xlsx"
;
format1 = ExportFormat.ExcelML;
break
;
case
"Word"
:
extension =
"doc"
;
format1 = ExportFormat.Html;
break
;
case
"CSV"
:
extension =
"csv"
;
format1 = ExportFormat.Csv;
break
;
}
var saveFileDialog =
new
SaveFileDialog
{
DefaultExt = extension,
Filter =
string
.Format(
"{0} files (*.{1})|*.{1}|All files (*.*)|*.*"
, format, extension),
FilterIndex = 1
};
if
(saveFileDialog.ShowDialog() ==
true
)
{
using
(Stream fileStream = saveFileDialog.OpenFile())
{
this
.GridView.Export(fileStream,
new
GridViewExportOptions
{
Format = format1,
ShowColumnFooters =
true
,
ShowColumnHeaders =
true
,
ShowGroupFooters =
false
});
}
}
}
public
void
SetGridLines(
string
gridLines)
{
if
(_wrappedGridView ==
null
)
return
;
// Reset all menu items
this
.gridLinesBoth.IsChecked =
false
;
this
.gridLinesHorizontal.IsChecked =
false
;
this
.gridLinesVertical.IsChecked =
false
;
this
.gridLinesNone.IsChecked =
false
;
var gridLinesVisibility = (GridLinesVisibility)Enum.Parse(
typeof
(GridLinesVisibility), gridLines,
true
);
if
(WebPortalGridView !=
null
)
{
if
(WebPortalGridView.VisualisationSettings ==
null
)
{
// Initialise if settings are null i.e. Non-dashboard
WebPortalGridView.VisualisationSettings = VisualisationSettingsViewModel.DefaultVisualisationSettings();
WebPortalGridView.VisualisationSettings.Control = WebPortalGridView;
}
// Set via visualisation
WebPortalGridView.VisualisationSettings.GridLines = gridLines;
}
else
{
// No grid so set grid lines manually
_wrappedGridView.GridLinesVisibility = (GridLinesVisibility)Enum.Parse(
typeof
(GridLinesVisibility), gridLines,
true
);
}
switch
(gridLinesVisibility)
{
case
GridLinesVisibility.Both:
this
.gridLinesBoth.IsChecked =
true
;
break
;
case
GridLinesVisibility.Horizontal:
this
.gridLinesHorizontal.IsChecked =
true
;
break
;
case
GridLinesVisibility.Vertical:
this
.gridLinesVertical.IsChecked =
true
;
break
;
default
:
this
.gridLinesNone.IsChecked =
true
;
break
;
}
}
private
void
filterToggle_Checked(
object
sender, RoutedEventArgs e)
{
if
(_wrappedGridView !=
null
)
_wrappedGridView.IsFilteringAllowed =
true
;
}
private
void
filterToggle_Unchecked(
object
sender, RoutedEventArgs e)
{
if
(_wrappedGridView !=
null
)
{
// Clear any filters that may be applied
_wrappedGridView.FilterDescriptors.Clear();
_wrappedGridView.IsFilteringAllowed =
false
;
}
}
private
void
groupingToggle_Checked(
object
sender, RoutedEventArgs e)
{
if
(_wrappedGridView !=
null
)
_wrappedGridView.ShowGroupPanel =
true
;
}
private
void
groupingToggle_Unchecked(
object
sender, RoutedEventArgs e)
{
if
(_wrappedGridView !=
null
)
{
// Clear any groupings that may be applied
_wrappedGridView.GroupDescriptors.Clear();
_wrappedGridView.ShowGroupPanel =
false
;
}
}
}
}
Many thanx,
Chris