web-dev-qa-db-fra.com

L’édition "EditItem" de DataGrid n’est pas autorisée pour cette vue "lorsqu’elle est liée à un WPG DataGrid

Cela fait au moins quatre heures que je lis à ce sujet, et il semble que ce soit le type de liste, mais j'ai une situation 

ObservableCollection qui a une propriété de collection.

Je définis le premier DataGrid, et dans la section

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

Tout se passe bien, tout est affiché à l'écran comme je m'y attendais ... mais:

  1. Si vous essayez de modifier les cellules DataGrid1, cela me le permet.
  2. Si vous essayez de modifier les cellules DataGrid2, cela me renvoie cette exception 'EditItem' is not allowed for this view 

Qu'est-ce que je rate ? 

Ceci est mon modèle:

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

EDIT: Code 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>
17
Juan Pablo Gomez

Merci à @nit qui me donne le bon chemin. Bien sûr, le problème réside sur la base Type de collections EF 

Hashet <T> Et Datagrid nécessite au moins une List <T> , en changeant toutes mes classes "celles générées par Entity Framework", me donne un autre problème, doit apporter des modifications manuellement, et j'ai un beaucoup d'entre eux. 

Ma solution a été de créer un convertisseur, qui a fait le sale boulot pour moi:

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

Et mettez-le sur la reliure de mon 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}}"

La seule chose à faire sur les ondes est de savoir comment créer un convertisseur générique, mais pour l’instant, cela fonctionne bien.

7
Juan Pablo Gomez

J'ai essayé ceci et le problème est que vous avez initialisé votre collection Level2 en tant que Hashset<>. IEditableCollectionView.EditItem() lève cette erreur en essayant de mettre à jour un élément dans Hashset<>. J'ai initialisé la collection en tant que List<> et tout fonctionnait bien.

Je ne suis pas sûr de savoir pourquoi il n'est pas capable de mettre à jour un élément dans un hachage, il faut approfondir la question. Mais changer le Hashset<> en List<> résoudra cette erreur.

J'espère que ça aide

Merci

17
Nitin

Vous pourriez essayer ceci. Associez un gestionnaire BeginningEdit à votre grille de données et pointez sur le code suivant:

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

Cela ne se produira que si vous parvenez à exploiter physiquement la bordure de la cellule. La source d'origine de l'événement est une bordure, et je pense que ce qui peut arriver ici remplace une zone de texte ou un autre élément éditable dont la source est attendue. Cette bordure non éditable est modifiée, ce qui provoque une exception enfouie dans le fichier EditItem n'est pas autorisé 'exception. L'annulation de cet événement RoutedEvent avant qu'il ne puisse s'afficher avec son Source d'origine non valide empêche cette erreur de se produire dans ses pistes. 

9
ouflak

J'ai également résolu ce problème en utilisant IsReadOnly="True"

4
Shouket Ali

Voici un convertisseur générique que j'ai utilisé

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

vous pouvez définir la propriété IsReadOnly. peut-être que l'exception ne se produit pas .... essayez-le dans un fichier xaml ..

IsReadOnly="True"
1
Joy

De manière plus courte, vous pouvez écrire:

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