I have a ListView that uses a GridView and it is bound to an observable collection. On load I populate the collection and it shows up in the UI as expected. The problem happens when I try to manipulate the ObservableCollection later on; if I call RemoveAt( n ) or Clear() on the collection I get an invalid cast exeception that can't convert MS.Internal.NamedObject to the type of object stored in the collection.
From what I have read the DataGrid uses NamedObject to support adding rows, I can't find any reference to NamedObject with list views though. Why is this exception happening and how I can fix the underlying problem without resorting to try/catch blocks around each Clear or RemoveAt?
Exception:
{"Unable to cast object of type 'MS.Internal.NamedObject' to type 'User'."}
ListView Initialization
<ListView Name="listViewUsers" Grid.Row="0" ItemsSource="{Binding Path=Users}" GridViewColumnHeader.Click="GridViewHeader_Click">
<ListView.Resources>
<DataTemplate x:Key="UserControl">
<StackPanel Orientation="Horizontal">
<Button
cmd:Click.Command="{Binding Path=Model.UserService.DeleteUserCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
cmd:Click.CommandParameter="{Binding Path=Content, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}"
>Delete</Button>
<Button
cmd:Click.Command="{Binding Path=Model.EditUserCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
cmd:Click.CommandParameter="{Binding Path=Content, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListViewItem}}}"> Edit</Button>
</StackPanel>
</DataTemplate>
<DataTemplate x:Key="IsEnabledTemplate">
<CheckBox IsChecked="{Binding IsEnabled}" IsEnabled="False" />
</DataTemplate>
<Style TargetType="{x:Type ListViewItem}">
<EventSetter Event="MouseDoubleClick" Handler="ListViewUser_DoubleClick" />
</Style>
</ListView.Resources>
<ListView.View>
<GridView>
<GridViewColumn CellTemplate="{StaticResource UserControl}" />
<GridViewColumn Header="Is Enabled" Width="auto" CellTemplate="{StaticResource IsEnabledTemplate}" />
<GridViewColumn Header="User Id" DisplayMemberBinding="{Binding Id}" />
<GridViewColumn Header="First Name" Width="auto" DisplayMemberBinding="{Binding FirstName}"/>
<GridViewColumn Header="Last Name" Width="auto" DisplayMemberBinding="{Binding LastName}"/>
<GridViewColumn Header="User Name" Width="auto" DisplayMemberBinding="{Binding UserName}" />
</GridView>
</ListView.View>
</ListView>
Code (heavily snipped):
public class UserService : IUserService
{
private readonly ILoggerFacade _logger;
private readonly IEventAggregator _eventAggregator;
private ObservableCollection<EnterpriseUser> _users;
public UserService( ILoggerFacade logger, IEventAggregator eventAggregator )
{
_users = new ObservableCollection<User>();
}
public ObservableCollection<EnterpriseUser> Users
{
get { return _users; }
}
public void DeleteUserCommand_Execute( User)
{
try
{
bool success = DeleteUser( user );
if( !success )
{
_logger.Log( string.Format( "Enable to delete user: {0}", user.ToString() ),
Category.Debug, Priority.None );
} else
{
_logger.Log( string.Format( "User deleted: {0}", user.ToString() ), Category.Debug,
Priority.None );
}
Users.Remove( user );
} catch( Exception e )
{
_logger.Log( String.Format( "Exception occurred while trying to delete user: {0}", e.Message ), Category.Exception, Priority.None );
}
}
}