New binding results to "Object reference not set to an instance of an object"

Janne 1 Reputation point
2020-05-06T07:00:50.313+00:00

Hi

I have a data source at MS SQL Server and an app which reads definition and data from db without tight integration. New tables and columns get created all the time.
I need to change binding names after data is read from db and before it is shown at UI because some column names might include illegal XAML property path characters - I do it by escaping every character and surround column names with brackets at AutoGeneratingColumn.

This works fine until data is modified - UI displays data ok but editing values results to break with null reference (when changing row context).
Where is the problem and how it can be corrected? Same problem is described in here and here but modifying data after changing binding is not discussed.

An example - upper datagrid without escaped column names does not show data when illegal characters on column names, lower datagrid with escaped column names shows data but editing breaks app on null reference.

<Window x:Class="WpfApp1.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:WpfApp1"  
        mc:Ignorable="d"  
        Title="MainWindow" Height="450" Width="800">  
    <Grid>  
        <StackPanel>  
        <DataGrid Name="r1" ItemsSource="{Binding Path=.}" /><!-- does not show data where column name is illegal-->  
            <DataGrid Name="r2" ItemsSource="{Binding Path=.}" AutoGenerateColumns="True" AutoGeneratingColumn="AutoGeneratingColumn"/>  
        </StackPanel>  
    </Grid>  
</Window>  

  

using System.Data;  
using System.Text;  
using System.Windows;  
using System.Windows.Controls;  
using System.Windows.Data;  
  
namespace WpfApp1  
{  
    public partial class MainWindow : Window  
    {  
        public MainWindow()  
        {  
            InitializeComponent();  
            DataTable dt1;  
            dt1 = new DataTable();  
            dt1.Columns.Add("valid name", typeof(string));  
            dt1.Columns.Add("min. flow", typeof(int));  
            dt1.Columns.Add("x w/o b", typeof(string));  
            dt1.Rows.Add(new object[] { "abc", 1, "yes" });  
            dt1.Rows.Add(new object[] { "xxx", 2, "maybe" });  
            r1.DataContext = dt1;  
            r2.DataContext = dt1;  
        }  
        private void AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)  
        {  
            //escaping every character with hat ^ and surround whole string with brackets  
            var columnName = (string)e.Column.Header;  
            var bindingBuilder = new StringBuilder(columnName.Length * 2 + 2);  
  
            bindingBuilder.Append('[');  
            foreach (var c in columnName)  
            {  
                bindingBuilder.Append('^');  
                bindingBuilder.Append(c);  
            }  
            bindingBuilder.Append(']');  
  
            //new binding  
            DataGridBoundColumn dataGridBoundColumn = e.Column as DataGridBoundColumn;  
            dataGridBoundColumn.Binding = new Binding(bindingBuilder.ToString());  
        }  
    }  
}  
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,700 questions
0 comments No comments
{count} votes

5 answers

Sort by: Most helpful
  1. Alex Li-MSFT 1,096 Reputation points
    2020-05-06T07:58:00.217+00:00

    Welcome to our Microsoft Q&A platform!

    You can try to add code AutoGenerateColumns="True"

      <DataGrid Name="r2" ItemsSource="{Binding Path=.}" AutoGeneratingColumn="AutoGeneratingColumn" AutoGenerateColumns="True"/>
    

    Thanks.

    0 comments No comments

  2. Janne 1 Reputation point
    2020-05-06T10:30:57.81+00:00

    Well that was missing but it does not correct the problem :-(

    0 comments No comments

  3. Janne 1 Reputation point
    2020-05-06T16:49:35.377+00:00

    I will also attach here the stack trace which tells absolutely nothing to me about the error position:

    System.NullReferenceException
      HResult=0x80004003
      Message=Object reference not set to an instance of an object.
      Source=PresentationFramework
      StackTrace:
       at System.Windows.Data.BindingGroup.UpdateValues()
       at System.Windows.Data.BindingGroup.UpdateAndValidate(ValidationStep validationStep)
       at System.Windows.Data.BindingGroup.CommitEdit()
       at System.Windows.Controls.DataGrid.OnExecutedCommitEdit(ExecutedRoutedEventArgs e)
       at System.Windows.Controls.DataGrid.OnExecutedCommitEdit(Object sender, ExecutedRoutedEventArgs e)
       at System.Windows.Input.CommandBinding.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
       at System.Windows.Input.CommandManager.ExecuteCommandBinding(Object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
       at System.Windows.Input.CommandManager.FindCommandBinding(Object sender, RoutedEventArgs e, ICommand command, Boolean execute)
       at System.Windows.Input.CommandManager.OnExecuted(Object sender, ExecutedRoutedEventArgs e)
       at System.Windows.UIElement.OnExecutedThunk(Object sender, ExecutedRoutedEventArgs e)
       at System.Windows.Input.ExecutedRoutedEventArgs.InvokeEventHandler(Delegate genericHandler, Object target)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
       at System.Windows.Input.RoutedCommand.ExecuteImpl(Object parameter, IInputElement target, Boolean userInitiated)
       at System.Windows.Input.RoutedCommand.Execute(Object parameter, IInputElement target)
       at System.Windows.Controls.DataGrid.EndEdit(RoutedCommand command, DataGridCell cellContainer, DataGridEditingUnit editingUnit, Boolean exitEditMode)
       at System.Windows.Controls.DataGrid.OnCurrentCellChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
       at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
       at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
       at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
       at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
       at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
       at System.Windows.DependencyObject.SetCurrentValueInternal(DependencyProperty dp, Object value)
       at System.Windows.Controls.DataGrid.set_CurrentCellContainer(DataGridCell value)
       at System.Windows.Controls.DataGrid.set_FocusedCell(DataGridCell value)
       at System.Windows.Controls.DataGridCell.OnAnyGotFocus(Object sender, RoutedEventArgs e)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
       at System.Windows.FrameworkElement.OnGotFocus(RoutedEventArgs e)
       at System.Windows.UIElement.IsFocused_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
       at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
       at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
       at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
       at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
       at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
       at System.Windows.DependencyObject.SetValue(DependencyPropertyKey key, Object value)
       at System.Windows.Input.FocusManager.OnFocusedElementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
       at System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
       at System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)
       at System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)
       at System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex, DependencyProperty dp, PropertyMetadata metadata, EffectiveValueEntry oldEntry, EffectiveValueEntry& newEntry, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType)
       at System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp, Object value, PropertyMetadata metadata, Boolean coerceWithDeferredReference, Boolean coerceWithCurrentValue, OperationType operationType, Boolean isInternal)
       at System.Windows.Input.FocusManager.SetFocusedElement(DependencyObject element, IInputElement value)
       at System.Windows.Input.KeyboardNavigation.UpdateFocusedElement(DependencyObject focusTarget)
       at System.Windows.FrameworkElement.OnGotKeyboardFocus(Object sender, KeyboardFocusChangedEventArgs e)
       at System.Windows.Input.KeyboardFocusChangedEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
       at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
       at System.Windows.Input.InputManager.ProcessStagingArea()
       at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
       at System.Windows.Input.KeyboardDevice.ChangeFocus(DependencyObject focus, Int32 timestamp)
       at System.Windows.Input.KeyboardDevice.TryChangeFocus(DependencyObject newFocus, IKeyboardInputProvider keyboardInputProvider, Boolean askOld, Boolean askNew, Boolean forceToNullIfFailed)
       at System.Windows.Input.KeyboardDevice.Focus(DependencyObject focus, Boolean askOld, Boolean askNew, Boolean forceToNullIfFailed)
       at System.Windows.Input.KeyboardDevice.Focus(IInputElement element)
       at System.Windows.UIElement.Focus()
       at System.Windows.Controls.DataGridCell.OnAnyMouseLeftButtonDown(MouseButtonEventArgs e)
       at System.Windows.Controls.DataGridCell.OnAnyMouseLeftButtonDownThunk(Object sender, MouseButtonEventArgs e)
       at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)
       at System.Windows.UIElement.OnMouseDownThunk(Object sender, MouseButtonEventArgs e)
       at System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler, Object genericTarget)
       at System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler, Object target)
       at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
       at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
       at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
       at System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)
       at System.Windows.UIElement.RaiseEvent(RoutedEventArgs args, Boolean trusted)
       at System.Windows.Input.InputManager.ProcessStagingArea()
       at System.Windows.Input.InputManager.ProcessInput(InputEventArgs input)
       at System.Windows.Input.InputProviderSite.ReportInput(InputReport inputReport)
       at System.Windows.Interop.HwndMouseInputProvider.ReportInput(IntPtr hwnd, InputMode mode, Int32 timestamp, RawMouseActions actions, Int32 x, Int32 y, Int32 wheel)
       at System.Windows.Interop.HwndMouseInputProvider.FilterMessage(IntPtr hwnd, WindowMessage msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at System.Windows.Interop.HwndSource.InputFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
       at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
       at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
       at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
       at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
       at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
       at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
       at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
       at System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame frame)
       at System.Windows.Application.RunDispatcher(Object ignore)
       at System.Windows.Application.RunInternal(Window window)
       at System.Windows.Application.Run(Window window)
       at System.Windows.Application.Run()
       at PDataUpdater.App.Main()
    
    0 comments No comments

  4. Alex Li-MSFT 1,096 Reputation points
    2020-05-07T06:10:46.613+00:00

    I know what you mean, I think the problem is that the column name of the database table has space.You could format the SQL select to have no spaces

    select [valid name] as 'valid_name' from table
    
    0 comments No comments

  5. Janne 1 Reputation point
    2020-05-07T08:23:10.077+00:00

    My purpose is to read any arbitrary data where I do not now the schema in advance into a .net datatable and show it on WPF datagrid (AutoGenerateColumns=true) for editing. Everything works fine until someone has created or will create a column at MS-SQL Server where an illegal character for WPF XAML parser exists - for example "Weight w/o motor (kg)". In this case "/" character is illegal for XAML parser and data value is not even shown on datagrid unless columnname is escaped in codebehind/ AutGeneratingColumn like in example.

    When columname is escaped then data is shown but updating value causes null reference when changing focus row.

    0 comments No comments