Home > front end >  Loading a UserControl in WPF DataGrid
Loading a UserControl in WPF DataGrid

Time:10-06

I am building a WPF MVVM application. I am trying to load a UserControl inside a Grid but the OnLoaded method doesn't fire.

Here is EventTrigger in the UserControl, called Selector:

<b:Interaction.Triggers>
        <b:EventTrigger EventName="Loaded">
            <b:InvokeCommandAction Command="{Binding onl oadedCommand}" />
        </b:EventTrigger>
</b:Interaction.Triggers>

Here is the code in SelectorViewModel:

public RelayCommand onl oadedCommand { get; set; }

public SelectorViewModel(MapService mapService)
{
      this.mapService = mapService ?? throw new ArgumentNullException(nameof(mapService));

      onl oadedCommand = new RelayCommand(OnLoaded);
}

public async void OnLoaded()
{
      AvailablePositions = await mapService.GetPositions();
      //other code
}

The View of the grid where the UserControl is loaded into:

<local:Selector Grid.Row="0" Margin="{StaticResource SmallLeftTopMargin}" />

The ViewModel of the grid, where the UserControl is loaded into:

public SelectorViewModel SelectorViewModel { get; set; }

public MapViewModel(MapService mapService)
{
      SelectorViewModel = new SelectorViewModel(mapService);
}

What could possibly be the reason the method is not called at all? I put a breakpoint in SelectorViewModel' s constructor and it hits it, but it doesn't hit the one in OnLoaded().

Is the fact that the method is async a problem?

EDIT:

I tried setting the command as:

OnLoadedCommand = new RelayCommand(async () => await onl oaded());

and changing the return type of OnLoaded from void to Task but it still didn't work.

CodePudding user response:

You can bind it with Command like below. I tested it works.

Xaml Code

       <DataGrid>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Loaded">
                <i:InvokeCommandAction Command="{Binding onl oadedCommand}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </DataGrid>

ViewModel

class MainWindowViewModel
    {
        public AsyncCommand onl oadedCommand { get; set; }

        public MainWindowViewModel()
        {
            onl oadedCommand = new AsyncCommand(async () => await onl oaded());
        }

        public async Task OnLoaded()
        {
            Console.WriteLine("Loaded");
        }
    }

Async Command

public interface IAsyncCommand : ICommand
{
    Task ExecuteAsync(object parameter);
}

public class AsyncCommand : AsyncCommandBase
{
    private readonly Func<Task> _command;
    public AsyncCommand(Func<Task> command)
    {
        _command = command;
    }
    public override bool CanExecute(object parameter)
    {
        return true;
    }
    public override Task ExecuteAsync(object parameter)
    {
        return _command();
    }
}

AsyncCommandBase

public abstract class AsyncCommandBase : IAsyncCommand
{
    public abstract bool CanExecute(object parameter);
    public abstract Task ExecuteAsync(object parameter);
    public async void Execute(object parameter)
    {
        await ExecuteAsync(parameter);
    }
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested  = value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    protected void RaiseCanExecuteChanged()
    {
        CommandManager.InvalidateRequerySuggested();
    }
}

I also recommend you to subscribe to Method as in the link here.

You can check here for more detailed information.

  • Related