c# - datagrid wpf ejemplo
La edición de DataGrid ''EditItem'' no está permitida para esta vista` cuando está vinculada a un DataGrid de WPF (8)
Aquí hay un convertidor genérico que utilicé
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);
}
}
He estado leyendo sobre esto al menos durante 4 horas, y parece ser el tipo de lista, pero tengo una situación:
Un ObservableCollection que tiene una propiedad de colección.
Defino el primer DataGrid, y en la sección
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<!-- second Datagrid here, binding to Level2 property of my Observable collection -->
</DataTemplate>
<DataGrid.RowDetailsTemplate>
Todo va bien, todas las cosas en pantalla como esperaba ... pero:
- Si intento modificar las celdas DataGrid1 me lo permite.
- Si intento modificar las celdas de DataGrid2, se lanzará esta excepción
''EditItem'' is not allowed for this view
Qué me estoy perdiendo ?
Este es mi modelo:
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;}
}
EDITAR: Código 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>
De manera más corta puedes escribir:
DataGrid.BeginningEdit += (s, ss) => ss.Cancel = true;
Intenté esto y el problema es que has inicializado tu colección de Hashset<>
como Hashset<>
. IEditableCollectionView.EditItem()
este error al intentar actualizar el elemento en Hashset<>
. Inicialicé la colección como List<>
y estaba funcionando bien.
No estoy seguro de por qué no puede actualizar el elemento en hashset, necesito profundizar en él. Pero cambiar el Hashset<>
a la List<>
solucionará este error.
Espero eso ayude
Gracias
Puede establecer la propiedad IsReadOnly. tal vez la excepción no ocurra ... inténtelo en el archivo xaml ...
IsReadOnly="True"
Resolví esto poniendo mi datagrid en modo de solo lectura
<DataGrid
Name="dtgBulkInsert"
CanUserSortColumns="True"
Height="300" Visibility="Collapsed" IsReadOnly="True">
....
También resolví este problema usando IsReadOnly="True"
.
Tks a @nit que me dan el camino correcto. Por supuesto el problema reside en el tipo base de colecciones EF
Hashet <T> Y Datagrid necesita al menos una Lista <T> , cambiando todas mis clases "aquellas generadas por Entity framework", dame otro problema, debo hacer cambios manualmente y tengo muchos de ellos.
Mi solución fue crear un convertidor, que hizo el trabajo sucio para mí:
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;
}
}
Y ponlo en el enlace de mi 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}}"
Lo único en el aire es cómo hacer un convertidor genérico, pero por ahora funciona bien.
Usted podría intentar esto. Adjunte un controlador BeginningEdit a su DataGrid y apunte a este código:
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;
}
Esto solo afectará si de alguna manera logras tocar físicamente el borde de la celda. El origen original del evento es un borde, y creo que lo que puede suceder aquí es en lugar de un cuadro de texto, u otro elemento editable que sea la fuente como se esperaba, este borde no editable se presenta para su edición, lo que provoca una excepción que está oculta en el '' EditItem no está permitido ''excepción. La cancelación de este evento RoutedEvent antes de que pueda aparecer con su OriginalSource no válido detiene el error que se produce en sus pistas.