1

I have the following problem. I have moved the DelegateCommand from the ViewModel to a separate class. And observe a property in the ViewModel. That works so far.

Then CanExecute will call the first one with NULL when the view is initialized. Which is also correct. Then the first time OnNavigatedTo is called and the TestModel is set. But than CanExecute is called again with NULL which is wrong. If OnNavigatedTo is then called a second time and the TestModel is set, the value is passed correctly to CanExecute methode.

CommandClass:

public class CommandFactory : BindableBase, ICommandFactory
{
#region Fields

private ICommand buttonTestCommandLocal;

#endregion

#region Properties

public ICommand ButtonTestCommand 
{
  get { return buttonTestCommandLocal ?? (buttonTestCommandLocal = new DelegateCommand<ITestModel>(ButtonTestCommand_Executed, ButtonTestCommand_CanExecute)); }
}

#endregion

#region Methods

private bool ButtonTestCommand_CanExecute(ITestModel parameter)
{
  return parameter != null;
}

private void ButtonTestCommand_Executed(ITestModel parameter)
{
  int x = 30;

  Console.WriteLine(x.ToString());
}

#endregion
}

public interface ICommandFactory
{
  ICommand ButtonTestCommand { get; }
}

ViewModel:

public class ButtonRegionViewModel : BindableBase, INavigationAware
{
#region Fields

private ITestModel testModelLocal;

#endregion

#region Constructors and destructors

public ButtonRegionViewModel(ICommandFactory commandFactory)
{
  CommandFactory = commandFactory;

  //Does not work
  if(commandFactory.ButtonTestCommand is DelegateCommand<ITestModel> buttonTestCommand)
    buttonTestCommand.ObservesProperty(()=> TestModel);
}

#endregion

#region Properties

public ITestModel TestModel
{
  get => testModelLocal;
  private set
  {
    SetProperty(ref testModelLocal, value);
    //Does work
    //if (CommandFactory.ButtonCommand is IModelCommand modelCommand)
    //  modelCommand.RaiseCanExecuteChanged();
  }
}

#endregion

#region Methods

public bool IsNavigationTarget(NavigationContext navigationContext)
{
  return true;
}

public void OnNavigatedFrom(NavigationContext navigationContext)
{
}

public void OnNavigatedTo(NavigationContext navigationContext)
{
  if (!(navigationContext.Parameters["Element"] is ITestModel testModel))
    return;

  TestModel = testModel;
}

#endregion
}

View:

<Grid>
<Grid.RowDefinitions>
  <RowDefinition Height="*"/>
  <RowDefinition Height="Auto"/>
  <RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Button Grid.Row="1" Margin="2" Padding="0"  HorizontalAlignment="Center" HorizontalContentAlignment="Center" 
        CommandParameter="{Binding Path=TestModel, Mode=OneWay}" Content="CommandFactory.ButtonTestCommand"
        Command="{Binding Path=CommandFactory.ButtonTestCommand}" Width="200" Height="100"/>
</Grid>

I have no idea why this doesn't work the first time. Since RaiseCanExecuteChanged works directly.

Thanks for all your help :-)

ascholz
  • 179
  • 1
  • 9
  • it does not work because the viewmodel containing the parameter is not done instantiating yet. you should expect null values and exceptions all across a wpf view – Bizhan Jul 05 '18 at 10:26
  • That's probably a little misleadingly written. After initializing when OnNavigate is called, TestModel = testModel is passed NULL at CanExecute the first time. The second time OnNavigate is used, CanExecute displays the correct parameter. – ascholz Jul 05 '18 at 10:46
  • I have hopefully updated my question to make it easier to understand. – ascholz Jul 05 '18 at 10:52
  • What happens if you add RaiseCanExecuteChanged at the end of OnNavigateTo? – Bizhan Jul 05 '18 at 10:55
  • It also work if raise the RaiseCanExecuteChanged(); in the Parameter. As you can see above. But why does ObservesProperty not work the first(second time after initialization) time. But when I move the Command back to the ViewModel everything works as expected with the ObservesProperty. – ascholz Jul 05 '18 at 11:01
  • I'm not sure about why. But AFAIR commands should be notified to reevaluate their canExecute – Bizhan Jul 05 '18 at 11:10
  • BTW, if you name something `IFactory`, it should really be a factory (design pattern). Your `ICommandFactory` is not a factory at all, this misleads other developers. – dymanoid Jul 09 '18 at 16:17
  • Thanks for pointing that out. I'll keep an eye on it in the future. Still not answering my question :-) – ascholz Jul 23 '18 at 13:07

0 Answers0