Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. WPF
  4. DataGrid Exception

DataGrid Exception

Scheduled Pinned Locked Moved WPF
csswpfwcfdesignhelp
6 Posts 2 Posters 2 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    Kevin Marois
    wrote on last edited by
    #1

    I have a DataGrid that allows users to define CSV file columns for a UI I'm creating. It's bound to an ObservableCollection. I have CanUserAddRows = true. Apparantly setting this to True exposes some strange bug. The grid's first column has a button:

        <DataGrid Grid.Row="2"
                  Grid.Column="0"
                  ItemsSource="{Binding ColumnInfos}"
                  HorizontalGridLinesBrush="LightGray"
                  VerticalGridLinesBrush="LightGray"
                  AutoGenerateColumns="False"
                  CanUserAddRows="True"
                  CanUserDeleteRows="True"
                  CanUserReorderColumns="False"
                  CanUserResizeColumns="False"
                  CanUserSortColumns="False"
                  BorderBrush="SteelBlue"
                  BorderThickness="1"
                  HeadersVisibility="Column"
                  HorizontalScrollBarVisibility="Auto"
                  VerticalScrollBarVisibility="Auto"
                  VerticalAlignment="Stretch"
                  Margin="5,0,5,5">
    
            <DataGrid.Resources>
                <local:BindingProxy x:Key="proxy" Data="{Binding IsColumnWidthVisibile}"/>
            </DataGrid.Resources>
    
            <DataGrid.Columns>
    
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Button Command="{Binding DeleteColumnCommand, RelativeSource={RelativeSource FindAncestor, 
                                                                            AncestorLevel=1, AncestorType={x:Type Window}}}"
                                    CommandParameter="{Binding}"
                                    Margin="2"
                                    Height="18"
                                    Width="18"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
    
                <DataGridTextColumn Header="Column Name" 
                                    Binding="{Binding ColumnName}"
                                    Width="\*"/>
    
                <DataGridTextColumn Header="Width"
                                    Binding="{Binding ColumnWidth}"
                                    Width="65"
                                    Visibility="{Binding Data, Conve
    
    Richard DeemingR 1 Reply Last reply
    0
    • K Kevin Marois

      I have a DataGrid that allows users to define CSV file columns for a UI I'm creating. It's bound to an ObservableCollection. I have CanUserAddRows = true. Apparantly setting this to True exposes some strange bug. The grid's first column has a button:

          <DataGrid Grid.Row="2"
                    Grid.Column="0"
                    ItemsSource="{Binding ColumnInfos}"
                    HorizontalGridLinesBrush="LightGray"
                    VerticalGridLinesBrush="LightGray"
                    AutoGenerateColumns="False"
                    CanUserAddRows="True"
                    CanUserDeleteRows="True"
                    CanUserReorderColumns="False"
                    CanUserResizeColumns="False"
                    CanUserSortColumns="False"
                    BorderBrush="SteelBlue"
                    BorderThickness="1"
                    HeadersVisibility="Column"
                    HorizontalScrollBarVisibility="Auto"
                    VerticalScrollBarVisibility="Auto"
                    VerticalAlignment="Stretch"
                    Margin="5,0,5,5">
      
              <DataGrid.Resources>
                  <local:BindingProxy x:Key="proxy" Data="{Binding IsColumnWidthVisibile}"/>
              </DataGrid.Resources>
      
              <DataGrid.Columns>
      
                  <DataGridTemplateColumn>
                      <DataGridTemplateColumn.CellTemplate>
                          <DataTemplate>
                              <Button Command="{Binding DeleteColumnCommand, RelativeSource={RelativeSource FindAncestor, 
                                                                              AncestorLevel=1, AncestorType={x:Type Window}}}"
                                      CommandParameter="{Binding}"
                                      Margin="2"
                                      Height="18"
                                      Width="18"/>
                          </DataTemplate>
                      </DataGridTemplateColumn.CellTemplate>
                  </DataGridTemplateColumn>
      
                  <DataGridTextColumn Header="Column Name" 
                                      Binding="{Binding ColumnName}"
                                      Width="\*"/>
      
                  <DataGridTextColumn Header="Width"
                                      Binding="{Binding ColumnWidth}"
                                      Width="65"
                                      Visibility="{Binding Data, Conve
      
      Richard DeemingR Offline
      Richard DeemingR Offline
      Richard Deeming
      wrote on last edited by
      #2

      The problem is in your RelayCommand<T> class, which indiscriminately tries to cast the command parameter to the specified type. Your DeleteCommand is an instance of RelayCommand<ColumnInfoEntity>, so it will try to cast the parameter to the ColumnInfoEntity. But for the "new item" row, the parameter will be passed the CollectionView.NewItemPlaceholder[^] value, which will be an MS.Internal.NamedObject instance. Hence the cast will fail, and your code will crash. Change the RelayCommand<T> to test whether the parameter is the expected type:

      private bool CanExecuteCore(T parameter)
      {
      return _canExecute is null || _canExecute(parameter);
      }

      public bool CanExecute(object parameter)
      {
      return parameter is T param && CanExecuteCore(param);
      }

      public void Execute(object parameter)
      {
      if (parameter is T param && CanExecuteCore(param))
      {
      _execute(param);
      }
      }


      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

      K 2 Replies Last reply
      0
      • Richard DeemingR Richard Deeming

        The problem is in your RelayCommand<T> class, which indiscriminately tries to cast the command parameter to the specified type. Your DeleteCommand is an instance of RelayCommand<ColumnInfoEntity>, so it will try to cast the parameter to the ColumnInfoEntity. But for the "new item" row, the parameter will be passed the CollectionView.NewItemPlaceholder[^] value, which will be an MS.Internal.NamedObject instance. Hence the cast will fail, and your code will crash. Change the RelayCommand<T> to test whether the parameter is the expected type:

        private bool CanExecuteCore(T parameter)
        {
        return _canExecute is null || _canExecute(parameter);
        }

        public bool CanExecute(object parameter)
        {
        return parameter is T param && CanExecuteCore(param);
        }

        public void Execute(object parameter)
        {
        if (parameter is T param && CanExecuteCore(param))
        {
        _execute(param);
        }
        }


        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

        K Offline
        K Offline
        Kevin Marois
        wrote on last edited by
        #3

        That did it. Thank you!

        In theory, theory and practice are the same. But in practice, they never are.” If it's not broken, fix it until it is. Everything makes sense in someone's mind.

        1 Reply Last reply
        0
        • Richard DeemingR Richard Deeming

          The problem is in your RelayCommand<T> class, which indiscriminately tries to cast the command parameter to the specified type. Your DeleteCommand is an instance of RelayCommand<ColumnInfoEntity>, so it will try to cast the parameter to the ColumnInfoEntity. But for the "new item" row, the parameter will be passed the CollectionView.NewItemPlaceholder[^] value, which will be an MS.Internal.NamedObject instance. Hence the cast will fail, and your code will crash. Change the RelayCommand<T> to test whether the parameter is the expected type:

          private bool CanExecuteCore(T parameter)
          {
          return _canExecute is null || _canExecute(parameter);
          }

          public bool CanExecute(object parameter)
          {
          return parameter is T param && CanExecuteCore(param);
          }

          public void Execute(object parameter)
          {
          if (parameter is T param && CanExecuteCore(param))
          {
          _execute(param);
          }
          }


          "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

          K Offline
          K Offline
          Kevin Marois
          wrote on last edited by
          #4

          OK, so that works fine now. Now I added an event trigger to the grid:

          When I run this, I get the exception

          System.InvalidOperationException: 'Items collection must be empty before using ItemsSource.'

          It's thrown in the class ItemCollection.cs. The ItemSource is set to an ObservableCollection which is loaded in the CTOR. This is why I hate the DataGrid. I commited this change. Any thoughts on this?

          In theory, theory and practice are the same. But in practice, they never are.” If it's not broken, fix it until it is. Everything makes sense in someone's mind.

          Richard DeemingR 1 Reply Last reply
          0
          • K Kevin Marois

            OK, so that works fine now. Now I added an event trigger to the grid:

            When I run this, I get the exception

            System.InvalidOperationException: 'Items collection must be empty before using ItemsSource.'

            It's thrown in the class ItemCollection.cs. The ItemSource is set to an ObservableCollection which is loaded in the CTOR. This is why I hate the DataGrid. I commited this change. Any thoughts on this?

            In theory, theory and practice are the same. But in practice, they never are.” If it's not broken, fix it until it is. Everything makes sense in someone's mind.

            Richard DeemingR Offline
            Richard DeemingR Offline
            Richard Deeming
            wrote on last edited by
            #5

            You've added the <i:EventTrigger> as a direct child of the grid. Looking at the documentation[^], it should be wrapped in an <i:Interation.Triggers> element instead.

            <DataGrid ...>
            <DataGrid.Resources>
            ...
            </DataGrid.Resources>

            <i:Interaction.Triggers>
                <i:EventTrigger EventName="AddingNewItem">
                    <i:InvokeCommandAction Command="{Binding NewItemAddedCommand}" CommandParameter="{Binding}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
            

            "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

            "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

            K 1 Reply Last reply
            0
            • Richard DeemingR Richard Deeming

              You've added the <i:EventTrigger> as a direct child of the grid. Looking at the documentation[^], it should be wrapped in an <i:Interation.Triggers> element instead.

              <DataGrid ...>
              <DataGrid.Resources>
              ...
              </DataGrid.Resources>

              <i:Interaction.Triggers>
                  <i:EventTrigger EventName="AddingNewItem">
                      <i:InvokeCommandAction Command="{Binding NewItemAddedCommand}" CommandParameter="{Binding}"/>
                  </i:EventTrigger>
              </i:Interaction.Triggers>
              

              "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

              K Offline
              K Offline
              Kevin Marois
              wrote on last edited by
              #6

              duh. Too many late nights Thanks

              In theory, theory and practice are the same. But in practice, they never are.” If it's not broken, fix it until it is. Everything makes sense in someone's mind.

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups