1

I have a command on a ViewModel which I use to navigate to a details page

public class InstalledMetersListViewModel : MvxViewModel
    , IMvxServiceConsumer<IInstallMeterRepository>
{
    public List<InstalledMeterListItemViewModel> List { get; set; } 

    public InstalledMetersListViewModel()
    {
        List = new List<InstalledMeterListItemViewModel>();
        foreach (var meter in this.GetService<IInstallMeterRepository>().GetInstalledMeters())
        {
            List.Add(new InstalledMeterListItemViewModel { Serial = meter.Serial, Description = meter.Description });
        }
    }

    public IMvxCommand ShowDetailsCommand
    {
        get
        {
            return new MvxRelayCommand<InstalledMeterListItemViewModel>(type => RequestNavigate<InstalledMeterListItemViewModel>(new {serial = type.Serial.ToString()}));
        }
    }
}

with this View

<ListBox ItemsSource="{Binding List}" x:Name="TheListBox">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Border BorderThickness="5,5,5,5" BorderBrush="White">
                <Grid Width="auto" HorizontalAlignment="Stretch" >
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="Auto"/>
                        <ColumnDefinition Width="1*"/>
                        <ColumnDefinition Width="Auto"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition />
                        <RowDefinition />
                    </Grid.RowDefinitions>

                    <TextBlock Text="S/N"/>
                    <TextBlock Text=" : " Grid.Column="1"/>
                    <TextBlock Text="{Binding Serial}" Grid.Column="2"/>

                    <TextBlock Text="Description" Grid.Row="1"/>
                    <TextBlock Text=" : " Grid.Column="1" Grid.Row="1"/>
                    <TextBlock Text="{Binding Description}" Grid.Column="2" Grid.Row="1"/>

                    <Button Content="Details" Grid.Column="3" Grid.RowSpan="2" Command="{Binding Path=DataContext.ShowDetailsCommand, ElementName=TheListBox}" CommandParameter="{Binding}"/>
                </Grid>
            </Border>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

The ViewModel I am navigating to is

public class InstalledMeterListItemViewModel : MvxViewModel,
    IMvxServiceConsumer<IInstallMeterRepository>
{

    public InstalledMeterListItemViewModel(string serial)
    {
        IInstalledMeter meter = this.GetService<IInstallMeterRepository>().GetMeter(Convert.ToDouble(serial));
        Description = meter.Description;
        Serial = meter.Serial;
    }

    public InstalledMeterListItemViewModel()
    {

    }

Problem accessing object - most likely this is caused by an anonymous object being generated as Internal - please see Anonymous types and Get accessors on WP7.1?

But I dont use any internal classes, so I cant see how I can fix this

Community
  • 1
  • 1
Mech0z
  • 3,627
  • 6
  • 49
  • 85
  • I'm actually surprised this runs on the emulator - I don't think it used to... – Stuart Nov 22 '12 at 13:24
  • Thats my bad, it dont, I was using the WP8 emulator and when I found out I only removed it from the title, editing now – Mech0z Nov 22 '12 at 14:01

1 Answers1

1

This line:

return new MvxRelayCommand<InstalledMeterListItemViewModel>(
         vm => RequestNavigate<InstalledMeterListItemViewModel>(
              new {serial = type.Serial.ToString()}));

creates an instance of an anonymous class

That anonymous class is generated by the compiler (use a tool like Reflector to see it)

The compiler generates it as internal

i.e. the compiler create a class a bit like

 internal class Anonymous_Mangled_Name_1223345tHER
 {
     public string serial { get; set; }
 }

and then rewrites your code as:

return new MvxRelayCommand<InstalledMeterListItemViewModel>(
         vm => RequestNavigate<InstalledMeterListItemViewModel>(
              new Anonymous_Mangled_Name_1223345tHER
              {
                  serial = type.Serial.ToString()
              }));

In order to reflect and use this class, the code in Cirrious.MvvmCross needs to get access to it...

That's why you need InternalsVisibleTo - http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx

See the last line of Conference-AssemblyInfo.cs for an example of the line to add.

[assembly: InternalsVisibleTo("Cirrious.MvvmCross")]

Note: for the old 'master' branch, this is:

[assembly: InternalsVisibleTo("Cirrious.MvvmCross.WindowsPhone")] 
// should really also add Cirrious.MvvmCross.Touch - but mono runtime doesn't care 
// should really also add Cirrious.MvvmCross.Droid - but mono runtime doesn't care 
Stuart
  • 66,722
  • 7
  • 114
  • 165
  • Adding [assembly: InternalsVisibleTo("Cirrious.MvvmCross")] to both my UI and Core WP7 project do not fix the error, it is still thrown – Mech0z Nov 22 '12 at 14:29
  • 1
    Using [assembly: InternalsVisibleTo("Cirrious.MvvmCross.WindowsPhone")] worked due to me running Master and not Vnext – Mech0z Nov 22 '12 at 14:55