First chance exception "Object must implement IConvertible."

Mar 1, 2012 at 12:55 PM
Edited Mar 1, 2012 at 12:56 PM

Hi,

first of all: this seems to be a great project. Thanks. I'm still quite new to MVVM, so these are some of my first steps.

I just started with my first test project with Catel. It seems so work but is very slow. The reason seems to be the first chance exceptions in the background, which I have no idea why they occur.

I have a main viewmodel called MainWindowViewModel. The only "data" is a list of Receipts (dataprop) and the currently selected Receipt:

public ObservableCollection<Receipt> Receipts
public Receipt SelectedReceipt 

I fill the values of the collection in the Initialize() method with test data.

base.Initialize();

            Ingredient i1 = new Ingredient { Name = "Methan", DangerClass = 0 };
            Ingredient i2 = new Ingredient { Name = "Buthan", DangerClass = 1 };
            Ingredient i3 = new Ingredient { Name = "Ethan", DangerClass = 2 };

            Receipt r1 = new Receipt { Name = "Good Mix",  ReceiptIngredients = new ObservableCollection<ReceiptIngredient>()};
            r1.ReceiptIngredients.Add(new ReceiptIngredient{ Ingredient = i1, Amount = 100, Unit = "g"});
            r1.ReceiptIngredients.Add(new ReceiptIngredient{ Ingredient = i2, Amount = 50, Unit = "g"});

            Receipt r2 = new Receipt { Name = "Bad Mix", ReceiptIngredients = new ObservableCollection<ReceiptIngredient>() };
            r2.ReceiptIngredients.Add(new ReceiptIngredient { Ingredient = i1, Amount = 50, Unit = "g" });
            r2.ReceiptIngredients.Add(new ReceiptIngredient { Ingredient = i2, Amount = 50, Unit = "g" });
            r2.ReceiptIngredients.Add(new ReceiptIngredient { Ingredient = i3, Amount = 33.33, Unit = "g" });
            
            Receipts = new ObservableCollection<Receipt> { r1, r2 };

            SelectedReceipt = Receipts.FirstOrDefault();

Now the main View is a tab control binding each Receipt to a tab.

<TabControl ItemsSource="{Binding Receipts}" Margin="0" SelectedItem="{Binding SelectedReceipt}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Name}"/>
            </StackPanel>
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate>
            <LocalControl:ReceiptUserControl DataContext="{Binding}"/>
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

As you can see I have a user control for the receipt (Catel user control based) which is called appropriately. It displays the name and the list of ingredients.

The ViewModel for the user control has the vmpropmodel and some viewmodeltopropmodel properties.

[Model]
public Receipt Receipt

[ViewModelToModel("Receipt")]
public string Name

[ViewModelToModel("Receipt")]
public ICollection<ReceiptIngredient> ReceiptIngredients
...

The model objects also are based on DataObjectBase. Now as soon as the binding to the TabControl happens, the constructor with the two parameters of the classes Ingredient and ReceiptIngredient are called (not Receipt) and the first chance exception occurs:

Exception:Thrown: "Object must implement IConvertible." (System.InvalidCastException)
A System.InvalidCastException was thrown: "Object must implement IConvertible."

at the following position

protected Ingredient(SerializationInfo info, StreamingContext context)
            : base(info, context) { }

First I do not understand why these contructors are called in the first place. The objects are already created, so the frameworks must try to serialize/deserialize them for some reason.

Next, why does this error occur...

I could send you my solution, if this is any help. Id does not yet contain database access, though this will be my next goal. I plan on using EF with poco classes. I want to try to still use your base class (I will need to add virtual to the properties to enable lazy loading at least).

Thanks for any advice, and again: Great Project!

Gorroux

Coordinator
Mar 1, 2012 at 1:11 PM

As soon as you define something with a [Model], under water it will call the IEditableObject interface (so the state can be reverted). Your models implement the DataObjectBase, which serializes binary to make sure its state can be reverted. For binary serialization, the constructor with the serialization info is required.

However, I don't know why the invalid cast exception occurs. Is there an explicit reason why you use ICollection instead of ObservableCollection?

Mar 5, 2012 at 8:56 AM

Hello Geert.

Thanks for the answer. The reason I use ICollection is habit. We use them in our EF POCO classes and I'm not sure how EF will react to use the ObservableCollection. But I will try this and tell you what happens :)

Still, if this is the reason for the behavior, it is a bit impractible.

Do you have any idea if EF + DataObjectBase will work together?

Gorroux

Mar 5, 2012 at 9:18 AM
Edited Mar 5, 2012 at 2:16 PM

Hi again.

The exceptions are history! ;-)

it is still very slow though. It takes me about 2 seconds to change the tab. But I do not know yet if there is a bug in myimplementation or if this is due to Catel.

Edit:

It is only slow if the debugger is attached. Running the same code by launching it from the explorer or using Ctrl-F5 the code runs fine. Otherwise it is VERY slow. Is this the default behavior or am I missing something?

Edit:

Oopps, the exceptions are still there. I forgot that I just see them in the IntelliTrace. Now I only use ObservableCollection, no ICollections :(

thanks again, G.x

Coordinator
Mar 5, 2012 at 6:23 PM

1) Are you using the latest 3.0 beta available from NuGet?

2) Try no to call the "RegisterDebugListener" in your app, saves you lots of code written to the console

Mar 6, 2012 at 9:17 AM

Using the 3.0 beta the problem is gone!

I cannot find the TraceOutputWindow though? Is this still available? Maybe this was the original problem.

Thanks!

Coordinator
Mar 6, 2012 at 9:18 AM

We removed the TraceOutputControl and Window because we never heard anyone talking about this. Maybe we will re-add it if there are enough requests.

Aug 9, 2013 at 9:51 AM
Could you please remove the information about TraceOutputWindow/-Control from CodeProject?
It's very confusing for people who are new to catel to read about a feature which can't be found anywhere in the code.
Thanks.
Coordinator
Aug 9, 2013 at 9:53 AM
The TraceOutputControl is back and can be found in the Catel.Extensions.Controls assembly:

https://catelproject.atlassian.net/wiki/display/CTL/TraceOutputControl
Aug 9, 2013 at 10:59 AM
GeertvanHorrik wrote:
The TraceOutputControl is back and can be found in the Catel.Extensions.Controls assembly:

https://catelproject.atlassian.net/wiki/display/CTL/TraceOutputControl
Thanks for the fast reply.