Here you go - an EmptyDataTemplate Attached property. (The blog posts a behavior)
I needed to set the template from code behind and I thought it would be great to have it be an Attached Property.
and other topics, a DataTemplate property can be set in code, from a Resource and using Style / Setter.
I added a default template so you can just set EmptyText="Your Text." if you do not need your own template.
To access the properties in your xaml, do not forget to add the reference - something like this
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Collections;
using Telerik.Windows.Data;
namespace Telerik.Windows.Controls.GridView
{
public class RadGridViewProperties
{
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#region EmptyDataTemplateHandler
internal class EmptyDataTemplateHandler
{
private RadGridView _grid;
private ContentPresenter _contentPresenter;
internal EmptyDataTemplateHandler(RadGridView grid)
{
_grid = grid;
Grid rootGrid = _grid.ChildrenOfType<Grid>().FirstOrDefault();
if (rootGrid != null)
{
LoadContentPresenter(rootGrid);
_grid.Items.CollectionChanged -= OnGridCollectionChanged;
_grid.Items.CollectionChanged += OnGridCollectionChanged;
SetVisibility();
}
}
internal void Unhook()
{
_grid.Items.CollectionChanged -= OnGridCollectionChanged;
}
private void OnGridCollectionChanged(object sender,
System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
SetVisibility();
}
private void LoadContentPresenter(Grid rootGrid)
{
_contentPresenter = new ContentPresenter();
_contentPresenter.IsHitTestVisible = false;
_contentPresenter.SetValue(Grid.RowProperty, 2);
_contentPresenter.SetValue(Grid.RowSpanProperty, 2);
_contentPresenter.SetValue(Grid.ColumnSpanProperty, 2);
_contentPresenter.SetValue(Border.MarginProperty, new Thickness(0, 27, 0, 0));
rootGrid.Children.Add(_contentPresenter);
}
private void SetVisibility()
{
if (_grid != null)
{
if (_contentPresenter != null)
{
if (_grid.Items.Count == 0)
{
LoadEmptyDataTemplate(); // Always load because it may be changed at any time
_contentPresenter.Visibility = Visibility.Visible;
}
else
_contentPresenter.Visibility = Visibility.Collapsed;
}
}
}
private void LoadEmptyDataTemplate()
{
var template = GetEmptyDataTemplate(_grid);
if (template == null)
template = GetDefaultTemplate();
_contentPresenter.ContentTemplate = template;
}
private DataTemplate GetDefaultTemplate()
{
string text = GetEmptyText(_grid);
if (String.IsNullOrEmpty(text))
text = "No Matching Records Found.";
var template = XamlReader.Load(String.Format(
xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
<TextBlock Text=""{0}"" HorizontalAlignment=""Center"" VerticalAlignment=""Center"" />
</DataTemplate>", text));
return (DataTemplate)template;
}
}
#endregion EmptyDataTemplateHandler
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
#region EmptyDataTemplate and EmptyText
/// <summary>
/// The template to use when there is no data to display in the grid
/// When not set and EmptyText is set, a default template is used
/// </summary>
/// <see cref="EmptyTextProperty"/>
public static readonly DependencyProperty EmptyDataTemplateProperty =
DependencyProperty.RegisterAttached("EmptyDataTemplate", typeof(DataTemplate),
typeof(RadGridView), new PropertyMetadata(OnEmptyDataTemplateChanged));
#region Accessors
/// <summary>
/// The template to use when there is no data to display in the grid
/// When not set and EmptyText is set, a default template is used
/// </summary>
/// <see cref="EmptyTextProperty"/>
public static DataTemplate GetEmptyDataTemplate(DependencyObject obj)
{
return (DataTemplate)obj.GetValue(EmptyDataTemplateProperty);
}
/// <summary>
/// The template to use when there is no data to display in the grid
/// When not set and EmptyText is set, a default template is used
/// </summary>
/// <see cref="EmptyTextProperty"/>
public static void SetEmptyDataTemplate(DependencyObject obj, DataTemplate value)
{
obj.SetValue(EmptyDataTemplateProperty, value);
}
#endregion Accessors
/// <summary>
/// The text to show when using the default EmptyDataTemplate.
/// Default text = "No Matching Records Found."
/// If EmptyDataTemplate is set, EmptyText is not used.
/// <see cref="EmptyDataTemplateProperty"/>
/// </summary>
public static readonly DependencyProperty EmptyTextProperty =
DependencyProperty.RegisterAttached("EmptyText", typeof(string),
typeof(RadGridView), new PropertyMetadata(OnEmptyTextChanged));
#region Accessors
/// <summary>
/// The text to show when using the default EmptyDataTemplate.
/// Default text = "No Matching Records Found."
/// If EmptyDataTemplate is set, EmptyText is not used.
/// <see cref="EmptyDataTemplateProperty"/>
/// </summary>
public static string GetEmptyText(DependencyObject obj)
{
return (string)obj.GetValue(EmptyTextProperty);
}
/// <summary>
/// The text to show when using the default EmptyDataTemplate.
/// Default text = "No Matching Records Found."
/// If EmptyDataTemplate is set, EmptyText is not used.
/// <see cref="EmptyDataTemplateProperty"/>
/// </summary>
public static void SetEmptyText(DependencyObject obj, string value)
{
obj.SetValue(EmptyTextProperty, value);
}
#endregion Accessors
#region EventHandlers
private static void OnEmptyDataTemplateChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var grid = d as RadGridView;
if (grid != null)
{
if (e.NewValue == null)
UnhookEmptyDataTemplate(grid);
else
HookEmptyDataTemplate(grid);
}
}
private static void OnEmptyTextChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var grid = d as RadGridView;
if (grid != null)
{
if (String.IsNullOrEmpty((String)e.NewValue))
UnhookEmptyDataTemplate(grid);
else
HookEmptyDataTemplate(grid);
}
}
private static void OnEmptyDataTemplateGridLoaded(object sender, EventArgs e)
{
if (InitEmptyDataTemplate(sender))
((RadGridView)sender).Loaded -= OnEmptyDataTemplateGridLoaded;
}
private static void OnEmptyDataTemplateGridDataLoaded(object sender, EventArgs e)
{
if (InitEmptyDataTemplate(sender))
((RadGridView)sender).DataLoaded -= OnEmptyDataTemplateGridDataLoaded;
}
#endregion EventHandlers
#region Implementation
/// <summary>
/// The ContentPresenter to used to hold the EmptyDataTemplate
/// This is used internally to store/retrieve the ContentPresenter
/// </summary>
internal static readonly DependencyProperty EmptyDataTemplateHandlerProperty =
DependencyProperty.RegisterAttached("EmptyDataTemplateHandler",
typeof(EmptyDataTemplateHandler), typeof(RadGridView), null);
#region Accessors
internal static EmptyDataTemplateHandler GetEmptyDataTemplateHandler(DependencyObject obj)
{
return (EmptyDataTemplateHandler)obj.GetValue(EmptyDataTemplateHandlerProperty);
}
internal static void SetEmptyDataTemplateHandler(DependencyObject obj,
EmptyDataTemplateHandler value)
{
EmptyDataTemplateHandler handler = GetEmptyDataTemplateHandler(obj);
if (handler != null)
handler.Unhook();
obj.SetValue(EmptyDataTemplateHandlerProperty, value);
}
#endregion Accessors
private static bool InitEmptyDataTemplate(object sender)
{
var grid = sender as RadGridView;
if (grid != null)
{
EmptyDataTemplateHandler handler = new EmptyDataTemplateHandler(grid);
return true;
}
return false;
}
private static void HookEmptyDataTemplate(RadGridView grid)
{ // Attach to Loaded, which will attach to CollectionChanged
UnhookEmptyDataTemplate(grid); // It does not hurt to unhook before hooking
grid.Loaded += OnEmptyDataTemplateGridLoaded;
grid.DataLoaded += OnEmptyDataTemplateGridDataLoaded;
}
private static void UnhookEmptyDataTemplate(RadGridView grid)
{ // Make sure events are no longer attached
grid.Loaded -= OnEmptyDataTemplateGridLoaded;
grid.DataLoaded -= OnEmptyDataTemplateGridDataLoaded;
SetEmptyDataTemplateHandler(grid, null);
}
#endregion Implementation
#endregion EmptyDataTemplate and EmptyDataText
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
} // RadGridViewProperties
}