【问题标题】:DataGrid edition 'EditItem' is not allowed for this view` when bound to a WPF DataGrid绑定到 WPF DataGrid 时,此视图不允许 DataGrid 版本“EditItem”
【发布时间】:2013-09-05 20:38:23
【问题描述】:

我已经阅读了至少 4 个小时,并且似乎是列表类型,但我有一个情况:

具有集合属性的 ObservableCollection。

我定义了第一个DataGrid,并在节中

<DataGrid.RowDetailsTemplate>
    <DataTemplate>
        <!-- second Datagrid here, binding to Level2 property of my Observable collection -->
    </DataTemplate>
<DataGrid.RowDetailsTemplate>

一切都很好,屏幕上的所有东西都如我所料......但是:

  1. 如果尝试修改 DataGrid1 单元格,我可以这样做。
  2. 如果尝试修改 DataGrid2 单元格,它会抛出此异常 'EditItem' is not allowed for this view

我错过了什么?

这是我的模型:

public partial class Level1
{
    public Level1()
    {
        this.Level2 = new HashSet<Level2>();
    }

    public decimal IdLevel1 { get; set; }
    public decimal IdLevel2 { get; set; }
    public string StrDescripcionTipoAsociado {get;set;}

    public virtual Level2 Level2{ get; set; }
}

public partial class Level2
{
    public decimal IdLevel1 { get; set; }
    public decimal IdLevel3 { get; set; }

    public virtual Level3 Level3{ get; set; }
}

public partial class Level3
{
    public decimal IdLevel3 { get; set; }
    public decimal NumIdConcepto {get;set;}
    public string StrDescripcionConcepto {get;set;}
}

编辑:XAML 代码:

    <DataGrid Grid.Row="1" 
              ItemsSource="{Binding Level1}" 
              AutoGenerateColumns="False" 
              SelectionMode="Single"
              GridLinesVisibility="Vertical"
              CanUserAddRows="True"
              CanUserDeleteRows="True"
              x:Name="GridTipoAsociado">
        <DataGrid.Columns>
            <DataGridTemplateColumn Header="Tipo de asociado" x:Name="TipoUsuarioSeleccionado">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Label Style="{StaticResource ResourceKey=FontElemNivel1}" Content="{Binding StrDescripcionTipoAsociado}"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
                <DataGridTemplateColumn.CellEditingTemplate>
                    <DataTemplate>
                        <TextBox Style="{StaticResource ResourceKey=FontElemNivel2}" Text="{Binding StrDescripcionTipoAsociado }"/>
                    </DataTemplate>
                </DataGridTemplateColumn.CellEditingTemplate>
            </DataGridTemplateColumn>
        </DataGrid.Columns>
        <DataGrid.RowDetailsTemplate>
            <DataTemplate>
                <DataGrid Grid.Row="1" 
                          ItemsSource="{Binding Level2}" 
                          AutoGenerateColumns="False" 
                          SelectionMode="Single"
                          SelectionUnit="Cell"
                          GridLinesVisibility="Vertical"
                          CanUserAddRows="True"
                          CanUserDeleteRows="True"                            
                          x:Name="GridItems">
                    <DataGrid.Columns>
                        <DataGridTemplateColumn Header="Id Item">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Label Content="{Binding NumIdConcepto}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTemplateColumn Header="Items">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <Label Content="{Binding Level3.StrDescripcionConcepto}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                            <DataGridTemplateColumn.CellEditingTemplate>
                                <DataTemplate>
                                    <TextBox Text="{Binding Level3.StrDescripcionConcepto}"/>
                                </DataTemplate>
                            </DataGridTemplateColumn.CellEditingTemplate>
                        </DataGridTemplateColumn>
                    </DataGrid.Columns>
                </DataGrid>
            </DataTemplate>
        </DataGrid.RowDetailsTemplate>
    </DataGrid>

【问题讨论】:

  • 您能否发布 DataGrid2 的 xaml 及其 itemsSource 集合的代码?
  • 是的,我要发布 xaml,但我没有任何代码。
  • Level3.StrDescriptcionConcepto。这个属性在哪里?
  • 抱歉在我的模型样本中丢失了
  • 如何将 ItemsSource 绑定到单个对象 ItemsSource="{Binding Level2}" ?应该是收藏

标签: c# wpf xaml datagrid


【解决方案1】:

我试过这个,问题是你已经将你的 Level2 集合初始化为Hashset&lt;&gt;IEditableCollectionView.EditItem() 在尝试更新 Hashset&lt;&gt; 中的项目时抛出此错误。 我将集合初始化为List&lt;&gt;,它工作正常。

我不确定为什么它无法更新哈希集中的项目,需要更深入地研究它。但是将Hashset&lt;&gt; 更改为List&lt;&gt; 将修复此错误。

希望对你有帮助

谢谢

【讨论】:

  • 原因是因为将Datagrid 的itemsource 绑定到Hashset 不会生成实现IEditableCollectionView 的集合视图。 List 会生成一个ListCollectionView,它确实实现了这个接口,这就是它起作用的原因。
  • 此代码由 EF 自动生成,此更改是否会影响性能。或者我的关系模型上的其他问题。?如果不是,为什么 EF 将集合定义为 hashet?
  • @nit 非常感谢您的帮助,现在我需要使用 EF 生成代码来维护我使用 List 而不是 Hashet 生成的类。再次非常感谢您的帮助。
  • 这让我想到了我的问题;就我而言,我只是愚蠢,并将网格绑定到 LINQ 查询的结果。解决方案是简单地将 .ToList() 添加到它的末尾。
【解决方案2】:

你可以试试这个。将BeginningEdit 处理程序附加到您的DataGrid 并指向此代码:

    private void Grid_BeginningEdit(object sender, DataGridBeginningEditEventArgs e)
    {
        //// Have to do this in the unusual case where the border of the cell gets selected.
        //// and causes a crash 'EditItem is not allowed'
        e.Cancel = true;
    }

只有当你设法以物理方式点击单元格的边界时,才会发生这种情况。事件的 OriginalSource 是一个边框,我认为这里可能发生的情况是,不是 TextBox 或其他可编辑元素作为预期的源,而是通过这个不可编辑的边框进行编辑,这会导致隐藏在 '不允许 EditItem 的例外。在此 RoutedEvent 使用其无效的 OriginalSource 冒泡之前取消此 RoutedEvent 可停止在其轨道中发生该错误。

【讨论】:

  • 这种方法对我来说效果很好。我还添加了一些“扭曲”以使其更窄:MyGrid.BeginningEdit += (sender, args) => args.Cancel = args.EditingEventArgs.OriginalSource is Border;
  • 这是一个很好的附加检查,我当时考虑过,但对我们的 UI 来说不是很有必要。
【解决方案3】:

感谢@nit,他给了我正确的道路。当然,问题在于 EF 集合的基本类型

Hashet 而Datagrid至少需要一个List,把我所有的类都改成“实体框架生成的那些”,给我又一个问题,必须手动进行更改,我有很多。

我的解决方案是创建一个转换器,这对我来说很麻烦:

public class listToObservableCollection : BaseConverter, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        HashSet<Level2> observableList = (HashSet<Level2>)value;
        return new ObservableCollection<Level2>(observableList);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (HashSet<Level2>)value;
    }
}

public abstract class BaseConverter : MarkupExtension
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}

并把它放在我的Datagrid2的绑定上:

<!--part of my window definition--!>
xmlns:l="clr-namespace:Recursos;assembly=Recursos"
...
<!--part of my resources section--!>
<l:listToObservableCollection x:Key="listoToObservable"/>
...
<!--part of my datagrid definition--!>
ItemsSource="{Binding Level2,Converter={StaticResource listoToObservable}}"

唯一正在播出的是如何制作通用转换器,但目前它工作正常。

【讨论】:

  • 我已经尝试过了,但我在 xaml 中的以下行中出现错误:ItemsSource="{Binding Source={StaticResource ModeloItensViewSource}, Converter={StaticResource collectionConverter}}"。错误是“值不能为空。参数名称:集合”。
  • @Marlon 抱歉耽搁了,请假几天。您是否正确定义了ModeloItensViewSource?为什么它是静态资源?
  • 我刚刚在互联网上的一些例子中看到了这种方式。但是我已经放弃了这个项目的实体框架。我遇到了太多错误和问题,对于一个小项目来说工作量太大了。也许以后我会花一些时间来研究它。不过还是感谢您的关注。
  • 有些东西经过努力会得到战利品,EF就是其中之一。也许 EF 不是问题,可能是设计,您是否使用 MVVM 作为开发模式?我大约有 2 个月的时间遇到​​了很多问题,现在我正在享受 EF 和 MVVM 的多功能性和强大功能。是一项证明长期合理的努力。如果您需要更多帮助,请告诉我。
  • 好的,谢谢。可能问题更像你所说的那样,更多的是设计而不是EF。但是对于项目的规模和研究所需的时间来说,这是不值得的。但我肯定会在未来的项目中考虑它。
【解决方案4】:

我也使用IsReadOnly="True" 解决了这个问题。

【讨论】:

    【解决方案5】:

    这是我使用的通用转换器

    public class ObservableCollectionConverter: IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var observableType= typeof (ObservableCollection<>).MakeGenericType(value.GetType().GetGenericArguments());
            return Activator.CreateInstance(observableType, value);
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var observableType = typeof(HashSet<>).MakeGenericType(value.GetType().GetGenericArguments());
            return Activator.CreateInstance(observableType, value);
        }
    }
    

    【讨论】:

      【解决方案6】:

      你可以用更短的方式写:

      DataGrid.BeginningEdit += (s, ss) => ss.Cancel = true;
      

      【讨论】:

        【解决方案7】:

        您可以设置 IsReadOnly 属性。也许不会发生异常... 在 xaml 文件中尝试一下..

        IsReadOnly="True"
        

        【讨论】:

          【解决方案8】:

          我解决了这个问题,将我的数据网格置于只读模式

          <DataGrid 
                          Name="dtgBulkInsert"
                          CanUserSortColumns="True" 
                          Height="300" Visibility="Collapsed" IsReadOnly="True">
          

          ....

          【讨论】:

            猜你喜欢
            • 2011-09-13
            • 2011-10-20
            • 2018-03-25
            • 2013-11-30
            • 2011-03-01
            • 1970-01-01
            • 1970-01-01
            • 2013-10-20
            相关资源
            最近更新 更多