none
ItemContainerGenerator.ContainerFromIndex()抛出了异常 RRS feed

  • 问题

  • 我在DataGrid删除行后,行号没有自动更新,故:我在OnUnloadingRow中加入更新行号的方法,结果发现Line07抛出System.NullReferenceException异常,位置在PresentationFramework.dll中

    01.protected override void OnUnloadingRow(DataGridRowEventArgs e) {  
    02.    base.OnUnloadingRow(e);  
    03.    if (this.Items != null ) {  
    04.        for (int i = 0; i < this.Items.Count; i++) {  
    05.  
    06.            try {  
    07.                DataGridRow row = this.ItemContainerGenerator.ContainerFromIndex(i) as DataGridRow;  
    08.                if (row != null) {  
    09.                    row.Header = (i + 1).ToString();  
    10.                }  
    11.            } catch { }  
    12.        }  
    13.    }  
    14.}  
    这是.Net FrameWork的Bug吗?或者有什么更好的方式“在DataGrid删除行后,更新行号”?

    Sonny.Lin

    2012年9月28日 1:37

答案

  • 我不清楚你的RowNumber的绑定是什么形式的,所以不能重现你的问题,我的一个行号的解决方案在下面列出:

                <DataGrid.RowHeaderTemplate>
                    <DataTemplate>
                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}, Converter={StaticResource RowNumberConverter}}" />
                    </DataTemplate>
                </DataGrid.RowHeaderTemplate>

        class DataGridRowNumberConverter : System.Windows.Data.IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
                return ((System.Windows.Controls.DataGridRow)value).GetIndex() + 1;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
                throw new NotImplementedException();
            }
        }

    private ObservableCollection<Book> sources = new ObservableCollection<Book>();
    
            public void InitializeDataContext() {
                sources.Add(new Book() { ID = 1, Title = "A", Price = 49.90, PublishDate = DateTime.Parse("2012-01-01") });
                sources.Add(new Book() { ID = 2, Title = "B", Price = 69.90, PublishDate = DateTime.Parse("2012-05-01") });
                sources.Add(new Book() { ID = 3, Title = "C", Price = 59.90, PublishDate = DateTime.Parse("2011-12-01") });
                datagrid.DataContext = sources;
            }
    
            private void Delete_Click(object sender, RoutedEventArgs e) {
                sources.Remove((Book)datagrid.SelectedItem);
                datagrid.Items.Refresh();
            }

    希望有所帮助。

    你的异常我猜想可能因为Items.Count没有刷新,导致溢出,当然只是猜想,你可以使用datagrid.Items.Refresh()方法试试能否处理。


    Wanpeng wanpeng.ones@gmail.com

    • 已标记为答案 qing2000 2012年9月28日 3:28
    2012年9月28日 3:04

全部回复

  • 反编译运行后,发现在for (ItemBlock block = this._itemMap.Next; block != this._itemMap; block = block.Next)发生异常,具体原因不详。

    public DependencyObject ContainerFromIndex(int index)
    {
        int num = 0;
        if (this.IsGrouping)
        {
            num = index;
            index = 0;
            int count = this.Items.Count;
            while (index < count)
            {
                CollectionViewGroup group = this.Items[index] as CollectionViewGroup;
                int num3 = (group == null) ? 1 : group.ItemCount;
                if (num < num3)
                {
                    break;
                }
                num -= num3;
                index++;
            }
        }
        for (ItemBlock block = this._itemMap.Next; block != this._itemMap; block = block.Next)
        {
            if (index < block.ItemCount)
            {
                DependencyObject obj2 = block.ContainerAt(index);
                GroupItem item = obj2 as GroupItem;
                if (item != null)
                {
                    obj2 = item.Generator.ContainerFromIndex(num);
                }
                return obj2;
            }
            index -= block.ItemCount;
        }
        return null;
    }
    
    


    Sonny.Lin

    2012年9月28日 1:47
  • 我不清楚你的RowNumber的绑定是什么形式的,所以不能重现你的问题,我的一个行号的解决方案在下面列出:

                <DataGrid.RowHeaderTemplate>
                    <DataTemplate>
                        <TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Text="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}, Converter={StaticResource RowNumberConverter}}" />
                    </DataTemplate>
                </DataGrid.RowHeaderTemplate>

        class DataGridRowNumberConverter : System.Windows.Data.IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
                return ((System.Windows.Controls.DataGridRow)value).GetIndex() + 1;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
                throw new NotImplementedException();
            }
        }

    private ObservableCollection<Book> sources = new ObservableCollection<Book>();
    
            public void InitializeDataContext() {
                sources.Add(new Book() { ID = 1, Title = "A", Price = 49.90, PublishDate = DateTime.Parse("2012-01-01") });
                sources.Add(new Book() { ID = 2, Title = "B", Price = 69.90, PublishDate = DateTime.Parse("2012-05-01") });
                sources.Add(new Book() { ID = 3, Title = "C", Price = 59.90, PublishDate = DateTime.Parse("2011-12-01") });
                datagrid.DataContext = sources;
            }
    
            private void Delete_Click(object sender, RoutedEventArgs e) {
                sources.Remove((Book)datagrid.SelectedItem);
                datagrid.Items.Refresh();
            }

    希望有所帮助。

    你的异常我猜想可能因为Items.Count没有刷新,导致溢出,当然只是猜想,你可以使用datagrid.Items.Refresh()方法试试能否处理。


    Wanpeng wanpeng.ones@gmail.com

    • 已标记为答案 qing2000 2012年9月28日 3:28
    2012年9月28日 3:04
  • datagrid.Items.Refresh();
    是有效刷新行号的方法。

    Sonny.Lin

    2012年9月28日 3:28