Hey,
I am using DataForm with custom field to display one of my complex properties for editing.
I am having an issue with Null reference exceptions from within the Telerik DataForm code when my control extends from a textbox.
I have reproduced the issue in a small sample app that doesn't have any of the complexities of my actual application.
What happens is if you run the application and click Ok or Cancel on the dataform buttons it will through a null reference exception.
This only happens if the HotKeyInputBox extens from a TextBox, if it extends from a Button or other type of control it doesn't throw the exception. Based on my implementation I need to extend it from a TextBox. I can't see any reason it should be throwing an exception.
Any help with getting this working would be fantastic.
MainWindow.xaml
<Window x:Class="DataFormBugDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:DataFormBugDemo"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<telerik:RadDataForm CurrentItem="{Binding Source={x:Static local:Setting.Instance}}"
AutoEdit="True" AutoGenerateFields="True" AutoGeneratingField="RadDataForm_OnAutoGeneratingField"/>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Windows;
using System.Windows.Data;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.Data.DataForm;
namespace DataFormBugDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
StyleManager.ApplicationTheme = new Office2019Theme();
Office2019Palette.LoadPreset(Office2019Palette.ColorVariation.Dark);
InitializeComponent();
}
private void RadDataForm_OnAutoGeneratingField(object sender, AutoGeneratingFieldEventArgs e)
{
e.DataField.DataMemberBinding.NotifyOnSourceUpdated = true;
e.DataField.DataMemberBinding.NotifyOnValidationError = true;
e.DataField.DataMemberBinding.ValidatesOnDataErrors = true;
e.DataField.DataMemberBinding.ValidatesOnNotifyDataErrors = true;
e.DataField.DataMemberBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
if (e.PropertyType == typeof(HotKey))
{
var dataField = new DataFormHotKeySettingsField()
{
Label = e.DataField.Label,
DataMemberBinding = e.DataField.DataMemberBinding,
Description = e.DataField.Description
};
e.DataField = dataField;
}
}
}
}
DataFormHotKeySettingsField.cs
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Telerik.Windows.Controls;
namespace DataFormBugDemo
{
public class DataFormHotKeySettingsField : DataFormDataField
{
protected override DependencyProperty GetControlBindingProperty()
{
return HotKeyInputBox.HotKeyProperty;
}
protected override Control GetControl()
{
var dependencyProperty = GetControlBindingProperty();
var inputBox = new HotKeyInputBox();
if (DataMemberBinding != null)
{
var binding = DataMemberBinding;
binding.Mode = BindingMode.TwoWay;
inputBox.SetBinding(dependencyProperty, binding);
}
inputBox.SetBinding(IsEnabledProperty, new Binding("IsReadOnly") { Source = this, Converter = new InvertedBooleanConverter() });
return inputBox;
}
}
}
HotKeyInputBox.cs
using System.Windows;
using System.Windows.Controls;
namespace DataFormBugDemo
{
class HotKeyInputBox : TextBox
{
public static readonly DependencyProperty HotKeyProperty = DependencyProperty.Register(
"HotKey", typeof(HotKey), typeof(HotKeyInputBox), new PropertyMetadata(default(HotKey)));
public HotKey HotKey
{
get { return (HotKey)GetValue(HotKeyProperty); }
set { SetValue(HotKeyProperty, value); }
}
public static readonly DependencyProperty DisplayTextProperty = DependencyProperty.Register(
"DisplayText", typeof(string), typeof(HotKeyInputBox), new PropertyMetadata(default(string)));
public string DisplayText
{
get { return (string)GetValue(DisplayTextProperty); }
set { SetValue(DisplayTextProperty, value); }
}
public HotKeyInputBox()
{
DisplayText = "None";
}
}
}
HotKey.cs
using System.Windows.Input;
namespace DataFormBugDemo
{
public class HotKey
{
public bool IsEnabled { get; set; }
public Key Key { get; set; }
}
}
Setting.cs
using PropertyChanged;
namespace DataFormBugDemo
{
[AddINotifyPropertyChangedInterface]
public class Setting
{
public static Setting Instance { get; }
static Setting()
{
Instance = new Setting();
}
public string Name { get; set; } = "Test Name";
public HotKey HotKey { get; set; } = new HotKey();
}
}
App.xaml
<Application x:Class="DataFormBugDemo.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:DataFormBugDemo"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
StartupUri="MainWindow.xaml">
<Application.Resources>
<!-- HotKeyInputBox -->
<ControlTemplate x:Key="HotKeyInputBoxTemplate" TargetType="local:HotKeyInputBox">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" BorderBrush="{Binding BorderBrush, RelativeSource={RelativeSource TemplatedParent}}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"
Padding="0" Name="PART_Border" VerticalAlignment="Center">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{TemplateBinding DisplayText}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Foreground="{TemplateBinding Foreground}"
MinWidth="150" Margin="0" />
</StackPanel>
</Border>
</Grid>
</ControlTemplate>
<Style TargetType="local:HotKeyInputBox">
<Setter Property="Template" Value="{StaticResource HotKeyInputBoxTemplate}" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="BorderBrush" Value="{telerik:Office2019Resource ResourceKey=MainBorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Background" Value="{telerik:Office2019Resource ResourceKey=SecondaryBackgroundBrush}" />
<Setter Property="Foreground" Value="{telerik:Office2019Resource ResourceKey=MainForegroundBrush}" />
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
</Style>
</Application.Resources>
</Application>