Reputation: 2896
The repo https://github.com/francotiveron/WpfApp1 contains the following projects:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
</Project>
using System;
using System.Windows.Input;
namespace WpfLibrary1
{
public static class CustomCommands
{
public static readonly RoutedCommand DifferentAssemblyCommand = new RoutedCommand("DifferentAssemblyCommand", typeof(CustomCommands));
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<Compile Include="Library.fs" />
</ItemGroup>
</Project>
namespace FsLibrary1
open System.Windows.Input
type CustomCommands =
static member FsAssemblyCommand = RoutedCommand("FsAssemblyCommand", typeof<CustomCommands>)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\FsLibrary1\FsLibrary1.fsproj" />
<ProjectReference Include="..\WpfLibrary1\WpfLibrary1.csproj" />
</ItemGroup>
</Project>
<Window x:Class="WpfApp3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp3"
xmlns:lib="clr-namespace:WpfLibrary1;assembly=WpfLibrary1"
xmlns:fs="clr-namespace:FsLibrary1;assembly=FsLibrary1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Content="SameAssemblyCommand" Command="local:CustomCommands.SameAssemblyCommand" HorizontalAlignment="Left" Margin="280,171,0,0" VerticalAlignment="Top" RenderTransformOrigin="-2.909,-2.677"/>
<Button Content="DifferentAssemblyCommand" Command="lib:CustomCommands.DifferentAssemblyCommand" HorizontalAlignment="Left" Margin="280,230,0,0" VerticalAlignment="Top" RenderTransformOrigin="-2.909,-2.677"/>
<Button Content="FsAssemblyCommand" Command="fs:CustomCommands.FsAssemblyCommand" HorizontalAlignment="Left" Margin="280,292,0,0" VerticalAlignment="Top" RenderTransformOrigin="-2.909,-2.677"/>
</Grid>
</Window>
namespace WpfApp3
{
public static class CustomCommands
{
public static readonly RoutedCommand SameAssemblyCommand = new RoutedCommand("SameAssemblyCommand", typeof(CustomCommands));
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var cmdBindings = new CommandBinding(CustomCommands.SameAssemblyCommand);
cmdBindings.Executed += SameAssemblyCommandExecuted;
//cmdBindings.CanExecute += OpenChartCanExecute1;
CommandBindings.Add(cmdBindings);
cmdBindings = new CommandBinding(WpfLibrary1.CustomCommands.DifferentAssemblyCommand);
cmdBindings.Executed += DifferentAssemblyCommandExecuted;
//cmdBindings.CanExecute += OpenChartCanExecute1;
CommandBindings.Add(cmdBindings);
cmdBindings = new CommandBinding(FsLibrary1.CustomCommands.FsAssemblyCommand);
cmdBindings.Executed += FsAssemblyCommandExecuted;
//cmdBindings.CanExecute += OpenChartCanExecute1;
CommandBindings.Add(cmdBindings);
}
private void FsAssemblyCommandExecuted(object sender, ExecutedRoutedEventArgs e) { }
private void SameAssemblyCommandExecuted(object sender, ExecutedRoutedEventArgs e) { }
private void DifferentAssemblyCommandExecuted(object sender, ExecutedRoutedEventArgs e) { }
}
}
The Binding to a command in the application assembly and in the C# library work as expected. Instead, the CommandBinding from the F# library doesn't work.
How can I make the F# CommandBinding work?
SOLUTION I didn't think that the F# syntax produces a property getter instead of a class field.
Upvotes: 2
Views: 51
Reputation: 17038
The problem is that your F# code is creating a new RoutedCommand
each time FsAssemblyCommand
is invoked. As a result, the corresponding command binding is never found in the element tree.
If you want this member to behave like a C# field that's only initialized once, you can use member val
instead:
type CustomCommands() =
static member val FsAssemblyCommand = RoutedCommand("OpenChartCommand", typeof<CustomCommands>)
Or you can create a let-bound value and return it each time:
type CustomCommands() =
static let cmd = RoutedCommand("OpenChartCommand", typeof<CustomCommands>)
static member FsAssemblyCommand = cmd
Upvotes: 2