-1

I'm trying to call a function in the viewmodel on startup the MVVM way. I thought I had it correct, but the code is never hitting the function call.

Here's my xaml:

<Window x:Class="TestWin.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
        xmlns:l="clr-namespace:Timeserver"
        xmlns:viewmodel="clr-namespace:Timeserver.ViewModels"
        Title="MainWindow"
        Width="893"
        Height="Auto"
        Background="LightGray"
        ResizeMode="NoResize"
        SizeToContent="Height">
    <Window.DataContext>
        <viewmodel:MainWindowViewModel />
    </Window.DataContext>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Loaded">
            <i:InvokeCommandAction Command="{Binding LoadData}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>

Here's my viewmodel (the necessary parts):

namespace TestWin.ViewModels
{
    class MainWindowViewModel
    {
        private StructsModel model; // my model class

        private ICommand loadDataCmd;

        private ICommand showTimeWindowCmd;

        private ICommand toggleExecuteCommand { get; set; }

        private bool canExecute = true;

        public bool CanExecute
        {            
            get
            {
                return this.canExecute;
            }

            set
            {
                if (this.canExecute == value)
                {
                    return;
                }

                this.canExecute = value;
            }
        }

        public ICommand ToggleExecuteCommand
        {
            get
            {
                return toggleExecuteCommand;
            }
            set
            {
                toggleExecuteCommand = value;
            }
        }

        public ICommand ShowTimeWindowCmd
        {
            //code here
        }

        public ICommand LoadDataCmd
        {
            get
            {
                return loadDataCmd;
            }
            set
            {
                loadDataCmd = value;
            }
        }

        public void LoadData(object parameter)
        {
            model.GetData();
        }

        public MainWindowViewModel()
        {
            this.model = new StructsModel();
            LoadDataCmd = new RelayCommand(LoadData, param => this.canExecute);
            ShowTimeWindowCmd = new RelayCommand(ShowTimeWindow, param => this.canExecute);
            toggleExecuteCommand = new RelayCommand(ChangeCanExecute);
        }

        public void ShowTimeWindow(object parameter)
        {
            //code here
        }

        public void ChangeCanExecute(object obj)
        {
            canExecute = !canExecute;
        }
    }
}

The function in question that is not being hit is LoadData(). It calls GetData() in my model class, which I cannot show for reasons. Not sure what else to try. I've seen other questions on SO doing the same thing I'm doing. My other function ShowTimeWindow is set up the exact same way and does get hit.

pfinferno
  • 1,779
  • 3
  • 34
  • 62
  • It seems that you don't really realize how the data binding works. I'd suggest you to get familiar with the WPF data binding engine. You're trying to bind to a method, which doesn't work. – dymanoid Nov 02 '16 at 15:14
  • I'll do more research, I was just looking at other questions on this site like this one: http://stackoverflow.com/a/17933290/2480598 Thought I could bind a command to a method. – pfinferno Nov 02 '16 at 15:21
  • 2
    shouldn't it be Binding LoadDataCmd instead of Binding LoadData? – Steve Nov 02 '16 at 15:26
  • Loaded has already probably been called prior to your view model being created. –  Nov 02 '16 at 15:49
  • You're right, I didn't catch that. – pfinferno Nov 02 '16 at 16:02
  • Also, @Steve, you are correct. Switching it to LoadDataCmd caused it to hit. Thank you. – pfinferno Nov 02 '16 at 16:10

2 Answers2

2

If you really want the call to be made at Loaded, you could remove the xaml code

<Window.DataContext>
    <viewmodel:MainWindowViewModel />
</Window.DataContext>

and bind the viewmode from code behind, like Mat said above. Then, the Command you have bound will be triggered (if it has the same name as the one in the viewmodel), and you will not need to call the vm.LoadData() in the constructor.

Also, if the command is not used for anything else than to load data at "Loaded", CanExecute is useless.

Lupu Silviu
  • 1,145
  • 11
  • 23
1

You can create your ViewModel in code behind. Than you can call the methods you need. If you want to go for excellence you can use a Factory pattern or a dependency injection container (e.g. Windsor)

public MainWindow()
{
    InitializeComponent();

    MainWindowViewModel vm = new MainWindowViewModel();

    DataContext = vm;

    vm.LoadData();
}
Mat
  • 1,960
  • 5
  • 25
  • 38