- GameDevMadeEasy
- Posts: 2
- Joined:
Using Noesis with F# and WPF
To use Noesis with F# and WPF, there are a few setup steps needed. First of which, we need to get a few packages from Nuget.
Let's use the Hello World Xaml file from the Samples. We will have to make some very slight modifications to it for it to work though. We can remove the xclass and the original local schema. We will make a new xmlns:local schema for clr-namespace: being Views and the assembly being the name of the application, in this case, it is NoesisFunctional. Everything else is exactly the same.
And that's it! You can run the application and it will run as intended.
Let's do a quick modification. One where we don't use FSXAML and just use Noesis.
If you would like an explanation of the F# code in depth, let me know. This was a very quick and fun little side project for me to work on but I figured I would share it with you guys so you can see Noesis working with a functional first language running on the .Net Framework.
After the packages have been installed, make sure you have all the appropriate references.
Let's define the App.xaml file.
We now need the app.xaml.fs file. We are pretty much following the conventions set forth in c# for this.<Application
xmlns="http://schemas.microsoft.com/winfx/2006 ... esentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="HelloWorld.xaml">
<Application.Resources>
</Application.Resources>
</Application>
This serves as the entry point of the program. Make sure to have the F# version of the using statement, which is the open statement for System.Windows and FsXamlopen System
open System.Windows
open FsXaml
type App = XAML<"App.xaml">
[<EntryPoint;STAThread>]
let main argv =
App().Run()
Let's use the Hello World Xaml file from the Samples. We will have to make some very slight modifications to it for it to work though. We can remove the xclass and the original local schema. We will make a new xmlns:local schema for clr-namespace: being Views and the assembly being the name of the application, in this case, it is NoesisFunctional. Everything else is exactly the same.
We can now make our HelloWorld.xaml.fs file. It pretty much mirrors the C# version only with F# syntax over C#.<Window xmlns:local="clr-namespace:Views;assembly=NoesisFunctional"
xmlns="http://schemas.microsoft.com/winfx/2006 ... esentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/marku ... ility/2006" mc:Ignorable="d"
Background="#FF124C7A"
Title="Hello, World!">
<Window.Resources>
<Storyboard x:Key="Intro">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" Storyboard.TargetName="Word">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="276.8">
<EasingDoubleKeyFrame.EasingFunction>
<CubicEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="GUI">
<EasingColorKeyFrame KeyTime="0" Value="#002AA6E2"/>
<EasingColorKeyFrame KeyTime="0:0:0.5" Value="#002AA6E2"/>
<EasingColorKeyFrame KeyTime="0:0:0.8" Value="#002AA6E2"/>
<EasingColorKeyFrame KeyTime="0:0:1.2" Value="#FF2AA6E2"/>
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)" Storyboard.TargetName="Logo">
<EasingDoubleKeyFrame KeyTime="0" Value="-4"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="Logo">
<EasingDoubleKeyFrame KeyTime="0" Value="-180"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<ExponentialEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="Logo">
<EasingDoubleKeyFrame KeyTime="0" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="Logo">
<EasingDoubleKeyFrame KeyTime="0" Value="0.5"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="Line1">
<EasingColorKeyFrame KeyTime="0" Value="#002AA6E2"/>
<EasingColorKeyFrame KeyTime="0:0:0.3" Value="#FF2AA6E2"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="Line2">
<EasingColorKeyFrame KeyTime="0" Value="#002AA6E2"/>
<EasingColorKeyFrame KeyTime="0:0:0.1" Value="#002AA6E2"/>
<EasingColorKeyFrame KeyTime="0:0:0.4" Value="#FF2AA6E2"/>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)" Storyboard.TargetName="Line3">
<EasingColorKeyFrame KeyTime="0" Value="#002AA6E2"/>
<EasingColorKeyFrame KeyTime="0:0:0.2" Value="#002AA6E2"/>
<EasingColorKeyFrame KeyTime="0:0:0.5" Value="#FF2AA6E2"/>
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)" Storyboard.TargetName="GUI">
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="1.1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<ExponentialEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)" Storyboard.TargetName="GUI">
<EasingDoubleKeyFrame KeyTime="0:0:0.5" Value="1"/>
<EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="1.1"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="1">
<EasingDoubleKeyFrame.EasingFunction>
<ExponentialEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="Hello">
<EasingColorKeyFrame KeyTime="0" Value="Transparent"/>
<EasingColorKeyFrame KeyTime="0:0:1" Value="Transparent"/>
<EasingColorKeyFrame KeyTime="0:0:1.3" Value="White">
<EasingColorKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut"/>
</EasingColorKeyFrame.EasingFunction>
</EasingColorKeyFrame>
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)" Storyboard.TargetName="World">
<EasingColorKeyFrame KeyTime="0" Value="Transparent"/>
<EasingColorKeyFrame KeyTime="0:0:1.2" Value="Transparent"/>
<EasingColorKeyFrame KeyTime="0:0:1.5" Value="White">
<EasingColorKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut"/>
</EasingColorKeyFrame.EasingFunction>
</EasingColorKeyFrame>
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="Hello">
<EasingDoubleKeyFrame KeyTime="0" Value="-40"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="-40"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.3" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" Storyboard.TargetName="World">
<EasingDoubleKeyFrame KeyTime="0" Value="-40"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="-40"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<SineEase EasingMode="EaseInOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleX)" Storyboard.TargetName="Hello">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1" Value="20"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.3" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseIn"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[1].(SkewTransform.AngleX)" Storyboard.TargetName="World">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.2" Value="20"/>
<EasingDoubleKeyFrame KeyTime="0:0:1.5" Value="0">
<EasingDoubleKeyFrame.EasingFunction>
<BackEase EasingMode="EaseIn"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
<BeginStoryboard Storyboard="{StaticResource Intro}"/>
</EventTrigger>
</Window.Triggers>
<Grid>
<Viewbox>
<Grid Width="325.8" Margin="24">
<Grid HorizontalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid x:Name="Logo" Grid.Column="0" RenderTransformOrigin="0.5,0.5" Width="49">
<Grid.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Grid.RenderTransform>
<Path x:Name="Line1" Data="M6.1,16 L13.7,5.7 32,8 35.7,16.7 39.4,11.9 35.5,3 11.2,0 0,15.2 3.8,24.1 9.5,24.8 6.1,16 z" Fill="#FF2AA6E2" VerticalAlignment="Center" Height="24.8" Margin="0,5.5,9.6,16.5"/>
<Path x:Name="Line2" Data="M15.5,6 L20.6,17.8 9.5,32.6 0,31.4 2.4,37 12.1,38.1 26.8,18.5 19.2,1.2 9.7,0 6.2,4.6 15.5,6.1 z" Fill="#FF2AA6E2" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" Height="38.1" Margin="22.2,0,0,8.7"/>
<Path x:Name="Line3" Data="M26,26.8 L13.3,25.4 6.1,8.4 6,8.4 11.8,0.8 5.7,0 0,7.8 9.5,30.3 28.4,32.5 34.1,24.8 31.9,19.4 z" Fill="#FF2AA6E2" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" Height="32.5" Margin="9.3,14.3,5.6,0"/>
</Grid>
<Grid x:Name="Word" Grid.Column="1" Width="276.8">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
<Path x:Name="Noesis" Data="M26.0999999999999,16.9L25.8,16.9C25.2,16.9 24.5999999999999,16.6999999999999 24.0999999999999,16.4 23.5999999999999,16.1 23.0999999999999,15.6999999999999 22.6999999999998,15.1999999999999L12.0999999999999,2.99999999999989C11.1999999999998,1.99999999999989 10.1999999999998,1.19999999999993 9.19999999999982,0.799999999999841 8.19999999999982,0.299999999999841 6.99999999999977,0.0999999999997954 5.49999999999977,0.0999999999997954L-2.27373675443232E-13,0.0999999999997954 -2.27373675443232E-13,21.9999999999998 5.19999999999982,21.9999999999998 5.19999999999982,5.19999999999982 5.49999999999977,5.19999999999982C6.09999999999968,5.19999999999982 6.69999999999982,5.39999999999986 7.19999999999982,5.69999999999982 7.79999999999973,5.99999999999977 8.19999999999982,6.39999999999986 8.59999999999991,6.89999999999986L19,18.9999999999999C19.9000000000001,20.0999999999999 20.9000000000001,20.8999999999999 21.9000000000001,21.3999999999999 23,21.8999999999999 24.2,22.0999999999999 25.8000000000002,22.0999999999999L31.3000000000002,22.0999999999999 31.3000000000002,-1.13686837721616E-13 26.1000000000001,-1.13686837721616E-13 26.0999999999999,16.9z M59.3,0L42.3999999999999,0C36.8999999999999,0,34.0999999999999,2.29999999999995,34.0999999999999,7L34.0999999999999,15C34.0999999999999,19.6,36.8999999999999,22,42.3999999999999,22L59.3,22C64.8,22,67.5999999999999,19.7,67.5999999999999,15L67.5999999999999,7C67.5999999999999,2.39999999999998,64.8,0,59.3,0z M62.2,15C62.2,16.2,61.2,16.9,59.3,16.9L42.3999999999999,16.9C40.4999999999998,16.9,39.4999999999998,16.3,39.4999999999998,15L39.4999999999998,7C39.4999999999998,5.70000000000005,40.4999999999998,5.10000000000002,42.3999999999999,5.10000000000002L59.3,5.10000000000002C61.2,5.10000000000002,62.2,5.70000000000005,62.2,7L62.2,15z M75.7,15.7999999999997L75.7,13.5999999999999 100.9,13.5999999999999 100.9,8.49999999999989 75.7,8.49999999999989 75.7,6.29999999999984C75.7,5.5999999999998,76.1000000000001,5.19999999999982,76.9000000000001,5.19999999999982L101,5.19999999999982 101,-2.27373675443232E-13 76.9000000000001,-2.27373675443232E-13C72.5,-2.27373675443232E-13,70.3000000000002,1.79999999999973,70.3000000000002,5.29999999999973L70.3000000000002,16.4999999999998C70.3000000000002,20.0999999999998,72.5000000000002,21.8999999999998,76.9000000000001,21.8999999999998L101.1,21.8999999999998 101.1,16.7999999999997 76.9000000000001,16.7999999999997C76.1000000000001,16.8999999999998,75.7,16.4999999999998,75.7,15.7999999999997z M128.5,8.39999999999998L110.2,8.39999999999998C109.4,8.39999999999998,108.9,8.10000000000002,108.9,7.60000000000002L108.9,5.89999999999998C108.9,5.39999999999998,109.3,5.10000000000002,110.2,5.10000000000002L134.4,5.10000000000002 134.4,0 110.2,0C105.8,0,103.6,1.79999999999995,103.6,5.29999999999995L103.6,8.79999999999995C103.6,11.9,105.8,13.5,110.2,13.5L128.5,13.5C129.3,13.5,129.7,13.8,129.7,14.3L129.7,16.0999999999999C129.7,16.5999999999999,129.3,16.8999999999999,128.5,16.8999999999999L104.3,16.8999999999999 104.3,21.9999999999999 128.5,21.9999999999999C132.9,21.9999999999999,135.1,20.1999999999999,135.1,16.6999999999999L135.1,13.6999999999999C135.1,10.1999999999999,132.9,8.39999999999998,128.5,8.39999999999998z M137.8,0L143.2,0 143.2,21.9 137.8,21.9z M170.8,8.39999999999998L152.5,8.39999999999998C151.7,8.39999999999998,151.2,8.10000000000002,151.2,7.60000000000002L151.2,5.89999999999998C151.2,5.39999999999998,151.6,5.10000000000002,152.5,5.10000000000002L176.7,5.10000000000002 176.7,0 152.5,0C148.1,0,145.9,1.79999999999995,145.9,5.29999999999995L145.9,8.79999999999995C145.9,11.9,148.1,13.5,152.5,13.5L170.8,13.5C171.6,13.5,172,13.8,172,14.3L172,16.0999999999999C172,16.5999999999999,171.6,16.8999999999999,170.8,16.8999999999999L146.6,16.8999999999999 146.6,21.9999999999999 170.8,21.9999999999999C175.2,21.9999999999999,177.4,20.1999999999999,177.4,16.6999999999999L177.4,13.6999999999999C177.3,10.1999999999999,175.1,8.39999999999998,170.8,8.39999999999998z" Fill="White" VerticalAlignment="Center" Margin="12,0,0,0"/>
<Path x:Name="GUI" Data="M61.9000244140625,16.1C61.9000244140625,16.6,61.5000244140624,16.9,60.7000244140625,16.9L41.5000244140624,16.9C40.7000244140625,16.9,40.2000244140625,16.6,40.2000244140625,16.1L40.2000244140625,0.100000000000023 34.8000244140624,0.100000000000023 34.8000244140624,16.7C34.8000244140624,20.3000000000001,37.0000244140624,22.1,41.4000244140623,22.1L60.6000244140623,22.1C65.0000244140624,22.1,67.2000244140622,20.3000000000001,67.2000244140622,16.8000000000001L67.2000244140622,1.13686837721616E-13 61.8000244140621,1.13686837721616E-13 61.8000244140621,16.1000000000001z M70.0000244140624,0L75.4000244140625,0 75.4000244140625,21.9 70.0000244140624,21.9z M20.1000244140623,8.60000000000002L20.1000244140623,14 26.8000244140624,14 26.8000244140624,16.9 6.60002441406232,16.9C5.80002441406236,16.9,5.30002441406236,16.5,5.30002441406236,15.8L5.30002441406236,6.19999999999993C5.30002441406236,5.49999999999989,5.70002441406245,5.09999999999991,6.60002441406232,5.09999999999991L31.6000244140623,5.09999999999991 31.6000244140623,-1.13686837721616E-13 6.60002441406232,-1.13686837721616E-13C2.20002441406223,-1.13686837721616E-13,2.44140624090505E-05,1.79999999999984,2.44140624090505E-05,5.29999999999984L2.44140624090505E-05,16.4999999999999C2.44140624090505E-05,20.0999999999999,2.20002441406245,21.8999999999999,6.60002441406232,21.8999999999999L32.2000244140622,21.8999999999999 32.2000244140622,8.49999999999989 20.1000244140623,8.49999999999989z" Fill="#FF2AA6E2" VerticalAlignment="Center" Margin="12,0,0,0" RenderTransformOrigin="1,0.5">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</StackPanel>
</Grid>
<StackPanel x:Name="HelloWorld" Grid.Row="1" Grid.ColumnSpan="2" Margin="0,15,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
<TextBlock x:Name="Hello" Text="Hello," FontSize="20" Foreground="White" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
<TextBlock x:Name="World" Text="World!" FontSize="20" Foreground="White" Margin="5,0,0,0" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform/>
</TransformGroup>
</TextBlock.RenderTransform>
</TextBlock>
</StackPanel>
</Grid>
</Grid>
</Viewbox>
</Grid>
</Window>
namespace FsXamlApp
#if NOESIS
open Noesis
open Noesis.App
#else
open FsXaml
open System.Windows
open Noesis
#endif
type MainWindow = XAML<"HelloWorld.xaml">
#if NOESIS
type MainWindow() as this =
let InitializeComponent = Noesis.GUI.LoadComponent(this, "HelloWorld.xaml");
#endif
And that's it! You can run the application and it will run as intended.
Let's do a quick modification. One where we don't use FSXAML and just use Noesis.
Now you can run the program and see Noesis doing its' thing.namespace FsXamlApp
open Noesis
open System.Windows
type MainWindow() as this =
let InitializeComponent = Noesis.GUI.LoadComponent(this, "HelloWorld.xaml");
If you would like an explanation of the F# code in depth, let me know. This was a very quick and fun little side project for me to work on but I figured I would share it with you guys so you can see Noesis working with a functional first language running on the .Net Framework.
-
sfernandez
Site Admin
- Posts: 2984
- Joined:
Re: Using Noesis with F# and WPF
Thanks a lot for sharing this with the community, it will be very useful for others looking for this.
Who is online
Users browsing this forum: No registered users and 92 guests