| Severity | Error |
| Reported by | Metalama.Patterns.Wpf |
| Message | No <Role> matching <CandidateNames> was found for the <MemberKind> '<Target>'. |
Cause
The [Command] and [DependencyProperty] aspects look for helper members by name. With the default naming convention, these members are optional: if no CanSave member or OnFooChanged method exists, the aspect simply works without it.
A helper member becomes required in the following situations, and Metalama reports LAMA5206 on the aspect's target when no member with the expected name exists:
- You set CanExecuteMethod or CanExecuteProperty in the
[Command]attribute. - You set PropertyChangedMethod or ValidateMethod in the
[DependencyProperty]attribute. - A custom naming convention requires the member, for example a CommandNamingConvention with CanExecutePatterns, which makes the can-execute member required unless IsCanExecuteRequired is
false.
The aspect isn't applied to the target. In the message, <Role> is the role of the missing member, for example property-changed method, <CandidateNames> is the expected name or pattern, <MemberKind> is command or dependency property, and <Target> is the aspect's target. For commands, <Role> always reads can-execute method or can-execute property, even when you set only one of the two attribute properties.
In the following example, the [Command] attribute names a can-execute method CanSaveDocument, but the class has no such method.
1using Metalama.Patterns.Wpf;
2
3namespace Doc.LAMA5206.Error;
4
5public class Document
6{
7 public bool IsModified { get; set; }
8
9 // Error: no method named CanSaveDocument exists.
10 [Command( CanExecuteMethod = "CanSaveDocument" )]
Error LAMA5206: No can-execute method or can-execute property matching 'CanSaveDocument' was found for the command 'Document.Save()'.
11 private void Save() { }
12
13 private bool CanSave() => this.IsModified;
14}
15
Resolution
- Check the spelling of the name in the attribute. The names are case-sensitive. Use
nameof, for example[Command( CanExecuteProperty = nameof(IsSaveEnabled) )], so that the compiler checks the name. - Check that the member has the right kind: CanExecuteMethod only looks for methods, and CanExecuteProperty only looks for properties. The member must be declared in the type of the aspect's target.
- Add the missing member if it doesn't exist yet.
- If the member is optional in your design, remove the explicit name from the attribute, or set
IsCanExecuteRequired = falsein your custom naming convention.
In the following example, the name in the attribute matches the existing CanSave method, and nameof makes the compiler check it.
1using Metalama.Patterns.Wpf;
2
3namespace Doc.LAMA5206.Fixed;
4
5public class Document
6{
7 public bool IsModified { get; set; }
8
9 // Fixed: the name matches the can-execute method.
10 [Command( CanExecuteMethod = nameof( CanSave ) )]
11 private void Save() { }
12
13 private bool CanSave() => this.IsModified;
14}
15
1using Metalama.Patterns.Wpf;
2
3namespace Doc.LAMA5206.Fixed;
4
5public class Document
6{
7 public bool IsModified { get; set; }
8
9 // Fixed: the name matches the can-execute method.
10 [Command(CanExecuteMethod = nameof(CanSave))]
11 private void Save() { }
12
13 private bool CanSave() => this.IsModified;
14
15 public Document()
16 {
17 SaveCommand = DelegateCommandFactory.CreateDelegateCommand(Save, CanSave);
18 }
19
20 public DelegateCommand SaveCommand { get; }
21}
22