diff --git a/src/ReactiveUI.WPF.SampleApp/ViewModels/QuestionnaireViewModel.cs b/src/ReactiveUI.WPF.SampleApp/ViewModels/QuestionnaireViewModel.cs index c4249523..3c3684c1 100644 --- a/src/ReactiveUI.WPF.SampleApp/ViewModels/QuestionnaireViewModel.cs +++ b/src/ReactiveUI.WPF.SampleApp/ViewModels/QuestionnaireViewModel.cs @@ -71,7 +71,7 @@ public QuestionnaireViewModel() vm => vm.AnswerFive, vm => vm.AnswerFiveLengthRemaining); - LaunchInteraction = ReactiveCommand.CreateFromTask(() => OnLaunchInteraction()); + LaunchInteraction = ReactiveCommand.CreateFromTask(OnLaunchInteraction); } /// diff --git a/src/ReactiveUI.WPF.SampleApp/Views/QuestionnaireView.xaml.cs b/src/ReactiveUI.WPF.SampleApp/Views/QuestionnaireView.xaml.cs index 0650aecf..81dfe8c5 100644 --- a/src/ReactiveUI.WPF.SampleApp/Views/QuestionnaireView.xaml.cs +++ b/src/ReactiveUI.WPF.SampleApp/Views/QuestionnaireView.xaml.cs @@ -25,6 +25,9 @@ public QuestionnaireView() private void OnWhenActivated(Action disposeWithAction) { +#if TBC + disposeWithAction(this.BindCommand(ViewModel, vw => vw.LaunchInteraction, vm => vm.LaunchInteraction)); +#endif new QuestionnaireViewBindingModels().ApplyBindings( disposeWithAction, this, diff --git a/src/Vetuviem.Core/CommandBinding.cs b/src/Vetuviem.Core/CommandBinding.cs index 5b30a0e8..76ab45a3 100644 --- a/src/Vetuviem.Core/CommandBinding.cs +++ b/src/Vetuviem.Core/CommandBinding.cs @@ -4,7 +4,6 @@ using System; using System.Linq.Expressions; -using System.Reactive; using System.Reactive.Disposables; using System.Windows.Input; using ReactiveUI; @@ -15,10 +14,10 @@ namespace Vetuviem.Core /// Represents a command binding between a control and a viewmodel. /// /// The type for the viewmodel. - public sealed class CommandBinding : ICommandBinding + public class CommandBinding : ICommandBinding where TViewModel : class { - private readonly Expression?>> _viewModelBinding; + private readonly Expression> _viewModelBinding; private readonly string? _toEvent; /// @@ -27,7 +26,7 @@ public sealed class CommandBinding : ICommandBindingExpression for the View Model binding. /// If specified, bind to the specific event instead of the default. public CommandBinding( - Expression?>> viewModelBinding, + Expression> viewModelBinding, string? toEvent = null) { _viewModelBinding = viewModelBinding; diff --git a/src/Vetuviem.SourceGenerator/Features/ControlBindingModels/ControlBindingModelPropertyGenerator.cs b/src/Vetuviem.SourceGenerator/Features/ControlBindingModels/ControlBindingModelPropertyGenerator.cs index 15bd8247..40fc6576 100644 --- a/src/Vetuviem.SourceGenerator/Features/ControlBindingModels/ControlBindingModelPropertyGenerator.cs +++ b/src/Vetuviem.SourceGenerator/Features/ControlBindingModels/ControlBindingModelPropertyGenerator.cs @@ -156,6 +156,8 @@ private static TypeSyntax GetBindingTypeSyntax( prop, desiredCommandInterface); +#error we need to change command to handle the control type instead of the property type. This is because BindCommand binds to the control, not the property. + var returnType = prop.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); var type = SyntaxFactory.ParseTypeName($"global::Vetuviem.Core.{bindingName}?"); return type; diff --git a/src/Vetuviem.SourceGenerator/Features/ControlBindingModels/GenericControlBindingModelClassGenerator.cs b/src/Vetuviem.SourceGenerator/Features/ControlBindingModels/GenericControlBindingModelClassGenerator.cs index 89d21671..b7f35d35 100644 --- a/src/Vetuviem.SourceGenerator/Features/ControlBindingModels/GenericControlBindingModelClassGenerator.cs +++ b/src/Vetuviem.SourceGenerator/Features/ControlBindingModels/GenericControlBindingModelClassGenerator.cs @@ -388,14 +388,23 @@ private static StatementSyntax[] GetApplyBindingMethodBody( continue; } - var propType = propertySymbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + var propType = propertySymbol.Type; + var propTypeDisplayString = propType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + + var isCommand = !string.IsNullOrWhiteSpace(desiredCommandInterface) && + (propType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat).Equals(desiredCommandInterface, StringComparison.Ordinal) + || propType.AllInterfaces.Any(interfaceName => interfaceName.GetFullName().Equals(desiredCommandInterface, StringComparison.Ordinal))); + + var expressionArg = isCommand + ? propertySymbol.Name + : $"global::Vetuviem.Core.ExpressionHelpers.GetControlPropertyExpressionFromViewExpression(VetuviemControlBindingExpression, \"{propertySymbol.Name}\")"; var invokeArgs = new[] { "registerForDisposalAction", "view", "viewModel", - $"global::Vetuviem.Core.ExpressionHelpers.GetControlPropertyExpressionFromViewExpression(VetuviemControlBindingExpression, \"{propertySymbol.Name}\")", + expressionArg, }; var invocationStatement = RoslynGenerationHelpers.GetMethodOnPropertyOfVariableInvocationSyntax( @@ -406,7 +415,7 @@ private static StatementSyntax[] GetApplyBindingMethodBody( AddInvocationStatementToRelevantCollection( propertySymbol, - desiredCommandInterface, + isCommand, invocationStatement, commandBindingStatements, oneWayBindingStatements, @@ -471,14 +480,23 @@ private static StatementSyntax[] GetApplyBindingCompositeDisposableMethodBody(IN continue; } - var propType = propertySymbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + var propType = propertySymbol.Type; + var propTypeDisplayString = propType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + + var isCommand = !string.IsNullOrWhiteSpace(desiredCommandInterface) && + (propType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat).Equals(desiredCommandInterface, StringComparison.Ordinal) + || propType.AllInterfaces.Any(interfaceName => interfaceName.GetFullName().Equals(desiredCommandInterface, StringComparison.Ordinal))); + + var expressionArg = isCommand + ? propertySymbol.Name + : $"global::Vetuviem.Core.ExpressionHelpers.GetControlPropertyExpressionFromViewExpression(VetuviemControlBindingExpression, \"{propertySymbol.Name}\")"; var invokeArgs = new[] { "compositeDisposable", "view", "viewModel", - $"global::Vetuviem.Core.ExpressionHelpers.GetControlPropertyExpressionFromViewExpression(VetuviemControlBindingExpression, \"{propertySymbol.Name}\")", + expressionArg, }; var invocationStatement = RoslynGenerationHelpers.GetMethodOnPropertyOfVariableInvocationSyntax( @@ -489,7 +507,7 @@ private static StatementSyntax[] GetApplyBindingCompositeDisposableMethodBody(IN AddInvocationStatementToRelevantCollection( propertySymbol, - desiredCommandInterface, + isCommand, invocationStatement, commandBindingStatements, oneWayBindingStatements, @@ -505,22 +523,16 @@ private static StatementSyntax[] GetApplyBindingCompositeDisposableMethodBody(IN private static void AddInvocationStatementToRelevantCollection( IPropertySymbol prop, - string? desiredCommandInterface, + bool isCommand, StatementSyntax invocation, ICollection commandBindingStatements, ICollection oneWayBindingStatements, ICollection twoWayBindingStatements) { - if (!string.IsNullOrWhiteSpace(desiredCommandInterface)) + if (isCommand) { - var propType = prop.Type; - var isCommand = propType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat).Equals(desiredCommandInterface, StringComparison.Ordinal) - || propType.AllInterfaces.Any(interfaceName => interfaceName.GetFullName().Equals(desiredCommandInterface, StringComparison.Ordinal)); - if (isCommand) - { - commandBindingStatements.Add(invocation); - return; - } + commandBindingStatements.Add(invocation); + return; } if (prop.IsReadOnly)