Calling a method on an instance of an object in WPF is not as easy to figure out, but with the help of this Internet thing I managed it.
Say you have a DataTemplate that renders a WorkItemType as a button that is selectable:
1 1: <DataTemplate DataType="{x:Type tfswitc:WorkItemType}">
1 2: <DockPanel>
1 3: <Image DockPanel.Dock="Left"
1 4: x:Name="wiImage"
1 5: Width="16"
1 6: Height="16"
1 7: Source="pack://application:,,/Resources/Images/WorkItems/unknown.gif">
1 8: </Image>
1 9: <Button x:Name="wiButton"
1 10: Content="{Binding Name}"
1 11: Style="{DynamicResource WelcomeButtonStyle}"
1 12: CommandParameter="{Binding}"
1 13: Command="Controlers:TeamSystemCommands.ChangeWorkItemTypeCommand">
1 14: </Button>
1 15: </DockPanel>
1 16: </DataTemplate>
Now, if I wanted to call a method on an instance of that WorkItemType and perform some action, then I would need a DataTrigger:
1 1: <DataTemplate DataType="{x:Type tfswitc:WorkItemType}">
1 2: <DockPanel>
1 3: <Image DockPanel.Dock="Left"
1 4: x:Name="wiImage"
1 5: Width="16"
1 6: Height="16"
1 7: Source="pack://application:,,/Resources/Images/WorkItems/unknown.gif">
1 8: </Image>
1 9: <Button x:Name="wiButton"
1 10: Content="{Binding Name}"
1 11: Style="{DynamicResource WelcomeButtonStyle}"
1 12: CommandParameter="{Binding}"
1 13: Command="Controlers:TeamSystemCommands.ChangeWorkItemTypeCommand">
1 14: </Button>
1 15: </DockPanel>
1 16: <DataTemplate.Triggers>
1 17: <DataTrigger Value="False">
1 18: <DataTrigger.Binding>
1 19: <Binding>
1 20: <Binding.Source>
1 21: <ObjectDataProvider ObjectType="{x:Type tfswitc:WorkItemType}"
1 22: MethodName="SupportedByHeat" />
1 23: </Binding.Source>
1 24: </Binding>
1 25: </DataTrigger.Binding>
1 26: <Setter TargetName="wiButton"
1 27: Property="IsEnabled"
1 28: Value="False" />
1 29: <Setter TargetName="wiButton"
1 30: Property="ToolTip"
1 31: Value="You will need to add the 'HeatITSM.Ref' field to use this work item." />
1 32: </DataTrigger>
1 33: </DataTemplate.Triggers>
1 34: </DataTemplate>
This will Call the method and if it returns false, it will disable the button and set a tooltip.
Now, this should work, but my SupportedByHeat method is an Extension method defined as:
1 1: Imports Microsoft.TeamFoundation.WorkItemTracking.Client
1 2:
1 3: Namespace TeamFoundationExtensions
1 4:
1 5:
1 6: Module WorkItemTypeExtensions
1 7:
1 8: <System.Runtime.CompilerServices.Extension()> _
1 9: Public Function SupportedByHeat(ByVal wit As WorkItemType) As Boolean
1 10: Dim c As Controlers.TeamSystemControler(Of MainWindow)
1 11: c = Application.ControlerFactory.GetControler(Of Controlers.TeamSystemControler(Of MainWindow))()
1 12: Return c.CheckWorkItemField(wit)
1 13: End Function
1 14:
1 15: End Module
1 16:
1 17: End Namespace
And this does not seam to work even if I import the namespace in the XAML:
1 1: <UserControl x:Class="SelectWorkItemType"
1 2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
1 3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
1 4: xmlns:d="http://schemas.microsoft.com/expression/blend/2006"
1 5: xmlns:tfs="clr-namespace:Microsoft.TeamFoundation.Client;assembly=Microsoft.TeamFoundation.Client"
1 6: xmlns:tfswitc="clr-namespace:Microsoft.TeamFoundation.WorkItemTracking.Client;assembly=Microsoft.TeamFoundation.WorkItemTracking.Client"
1 7: xmlns:tfse="clr-namespace:Hinshelwood.TFSHeatITSM.TeamFoundationExtensions"
1 8: xmlns:local="clr-namespace:Hinshelwood.TFSHeatITSM"
1 9: xmlns:Controlers="clr-namespace:Hinshelwood.TFSHeatITSM.Controlers"
1 10: xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
1 11: mc:Ignorable="d">
The error message that is received is:
System.Windows.Data Error: 34 : ObjectDataProvider: Failure trying to invoke method on type; Method=‘SupportedByHeat’; Type=‘WorkItemType’; Error=‘No method was found with matching parameter signature.’ MissingMethodException:‘System.MissingMethodException: Method ‘Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItemType.SupportedByHeat’ not found.
at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)_at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args, CultureInfo culture)
at System.Windows.Data.ObjectDataProvider.InvokeMethodOnInstance(Exception& e)’_
As you can see, during the binding the extension method is not evaluated.
During my investigation I came across WPFix Part 3 (Extension Methods) that intoned that there is indeed some solution, but it is complicated requiring the use of Lambda expressions.
I am looking for an easy solution :)
No related videos found.
If you've made it this far, it's worth connecting with our principal consultant and coach, Martin Hinshelwood, for a 30-minute 'ask me anything' call.
We partner with businesses across diverse industries, including finance, insurance, healthcare, pharmaceuticals, technology, engineering, transportation, hospitality, entertainment, legal, government, and military sectors.
NIT A/S
NIT A/S