question

11626390 avatar image
0 Votes"
11626390 asked 11626390 rolled back

System.TypeLoadException occurs in the Release Mode.

I am trying to attach an event handler in ListView with Microsoft.Xaml.Interactivity in my UWP application. When I select a row in ListView, the application executes a procedure according to the selected item.

So, I've installed the "Microsoft.Xaml.Behaviors.Uwp.Managed" package and changed a XAML file like this:

<ListView VerticalAlignment="Stretch"
x:Name="listBoxobj"
HorizontalAlignment="Stretch"
Margin="10,0,0,10"
Background="White"
Foreground="Black"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ItemsSource="{Binding Tools}"
SelectedItem= "{Binding SelectedItem, Mode=Twoway}"
SelectionMode="Single">
<Interactivity:Interaction.Behaviors>
<Interactions:EventTriggerBehavior EventName="ItemClick" SourceObject="listBoxObj">
<Interactions:InvokeCommandAction Command="{Binding Tool_Clicked}" CommandParameter="{Binding SelectedItem}" />
</Interactions:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
And the following has been implemented in its ViewModel:

private System.Windows.Input.ICommand tool_Clicked;
public ICommand Tool_Clicked
{
get {
return tool_Clicked;
}
set {
if (!Object.ReferenceEquals(tool_Clicked, value))
{
tool_Clicked = value as RelayCommand;
OnPropertyChanged("Tool_Clicked");
}
}
}
public DisplayViewModel()
{
...
Tool_Clicked = new RelayCommand(SelectionChanged);
...
}
public void SelectionChanged(object arg) {
... executes some procedures according to the selected item...
}
But when I tested these codes, the following exception has emitted: System.TypeLoadException: 'Could not find Windows Runtime type 'System.Windows.Input.ICommand'.'

In Debug mode, on the other hand, no such exception has been thrown. So, I have two questions:

  1. I wonder what is the difference betweeen the Debug mode and the Release mode.

  2. Are there any way to avoid throwing the System.TypeLoadException?

Update 1: I have configured the compile options at Release mode.

  • I've checked "Compile with .NET native tool chain"

  • I've checked "unsafe code".
    But when I tried to build my project, it has ended with the following error message: error : MCG0018:TypeExpected Type File or assembly 'System.Runtime.InteropServices.WindowsRuntime.PropertyType' not found.

I'm afraid what I did was totally wrong...





windows-uwp
· 2
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Cloud you share your RelayCommand class ?

0 Votes 0 ·

     public class RelayCommand : ICommand
     {
         private readonly Action<Object> _execute;
         private readonly Func<object, bool> _canExecute;
    
         public event EventHandler CanExecuteChanged;
         public RelayCommand(Action<object> execute) :
             this(execute, null)
         { }
         public RelayCommand(Action<object> execute, Func<object, bool> canExecute)
         {
             _execute = execute ?? throw new ArgumentNullException("execute");
             _canExecute = canExecute;
         }
         public bool CanExecute(object parameter)
         {
             return _canExecute == null ? true : _canExecute(parameter);
         }
         public void Execute(object parameter)
         {
             _execute(parameter);
         }
         public void RaiseCanExecuteChanged()
         {
             CanExecuteChanged?.Invoke(this, EventArgs.Empty);
         }
     }
0 Votes 0 ·

1 Answer

NicoZhu-MSFT avatar image
0 Votes"
NicoZhu-MSFT answered

Hello, Welcome to Micorosoft Q&A,

System.TypeLoadException occurs in the Release Mode.

It's not good practice to send SelectedItem as parameter, because the click event triggered before item selected that will make current parameter always previous selected value.

The better way is listen listviewitem Tapped event, and pass current datacontext as parameter.

For example


 <Page.DataContext>
     <local:ViewModel x:Name="MyViewModel" />
 </Page.DataContext>
 <Grid>
     <ListView
         x:Name="listBoxObj"
         IsItemClickEnabled="True"
         ItemsSource="{Binding Tools}"
         SelectedIndex="1"
         SelectedItem="{Binding SelectedItem, Mode=Twoway}"
         SelectionMode="Single">
         <ListView.ItemContainerStyle>
             <Style TargetType="ListViewItem">
                 <Setter Property="HorizontalContentAlignment" Value="Stretch" />
             </Style>
         </ListView.ItemContainerStyle>
         <ListView.ItemTemplate>
             <DataTemplate>
                 <TextBlock Text="{Binding}">
                     <Interactivity:Interaction.Behaviors>
                         <Interactions:EventTriggerBehavior EventName="Tapped">
                             <Interactions:InvokeCommandAction Command="{Binding ElementName=listBoxObj, Path=DataContext.Tool_Clicked}" CommandParameter="{Binding}" />
                         </Interactions:EventTriggerBehavior>
                     </Interactivity:Interaction.Behaviors>
                 </TextBlock>
             </DataTemplate>
         </ListView.ItemTemplate>
     </ListView>
 </Grid>

Code Behind

 public class ViewModel : INotifyPropertyChanged
 {
     public ObservableCollection<string> Tools { get; set; } = new ObservableCollection<string>();
     private string _selectItem;
    
     public string SelectedItem
     {
         get => _selectItem;
         set
         {
             _selectItem = value;
             OnPropertyChanged();
         }
     }
     public ViewModel()
     {
         for (int i = 0; i < 10; i++)
         {
             Tools.Add($"item---{i}");
         }
           
     }
    
     public ICommand Tool_Clicked => new RelayCommand<string>((s) =>
     {
         System.Diagnostics.Debug.WriteLine(s.ToString());
    
    
     });
    
     public event PropertyChangedEventHandler PropertyChanged;
     public void OnPropertyChanged([CallerMemberName] string propertyName = null)
     {
         // Raise the PropertyChanged event, passing the name of the property whose value has changed.
         this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
     }
 }
    
 public class RelayCommand<T> : ICommand
 {
     public event EventHandler CanExecuteChanged;
    
     public Action<T> action;
     public bool CanExecute(object parameter)
     {
         return true;
     }
    
     public void Execute(object parameter)
     {
         this.action((T)parameter);
     }
     public RelayCommand(Action<T> action)
     {
         this.action = action;
    
     }
 }



If the response is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.






5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.