绑定到WPF DataGrid时,此视图不允许使用DataGrid版本的“EditItem”

时间:2013-09-02 17:29:06

标签: c# wpf xaml datagrid

我至少在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
  3. 我错过了什么?

    这是我的模特:

    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>
    

8 个答案:

答案 0 :(得分:19)

我试过了,问题是您已将Level2集合初始化为Hashset<>。尝试更新IEditableCollectionView.EditItem()中的项目时,Hashset<>会引发此错误。 我将集合初始化为List<>,并且工作正常。

我不确定为什么它无法更新hashset中的项目,需要深入研究它。但是,将Hashset<>更改为List<>将解决此错误。

希望有所帮助

由于

答案 1 :(得分:9)

你可以试试这个。将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冒泡,停止在其轨道中发生该错误。

答案 2 :(得分:7)

告诉@nit谁给了我正确的道路。当然问题在于基本的EF集合类型

<强> Hashet&LT; T&gt; 并且Datagrid至少需要一个 List&lt; T&gt; ,更改我的所有类“由Entity框架生成的那些”,给我另一个问题,必须手动进行更改,我有很多。

我的解决方案是创建一个转换器,让我的脏工作:

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}}"

唯一的问题是如何制作通用转换器,但现在它工作正常。

答案 3 :(得分:5)

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

答案 4 :(得分:3)

这是我使用的通用转换器

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);
    }
}

答案 5 :(得分:1)

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

IsReadOnly="True"

答案 6 :(得分:0)

您可以用更短的方式撰写:

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

答案 7 :(得分:-2)

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

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

....