What Was Changed?
For the F# Windows App (WPF, MVVM) template, a few WPF behaviors have been added. I'll talk about these changes in a bit (for those that can't wait, see http://fssnip.net/62 and http://fssnip.net/6h).
The F# and C# Windows App (WPF, MVVM) template includes all of the same changes as the F# only template. Additionally, I've taken the multiple F# projects that were previously provided in this template and coalesced them into one F# project. I believe that this change better reflects the real-world use of this template.
You Mentioned WPF Behaviors?
The biggest change to the templates is the addition of examples of a few different types of WPF behaviors. These templates include examples of event to command as well as a type converter. The event to command implementation is Blendable (meaning that it plays well with Expression Blend) and is loosely based on the MVVM Light Toolkit EventToCommand implementation.
Here's the code:
namespace FSharpWpfMvvmTemplate.Behavior
open System
open System.Windows
open System.Windows.Input
open System.Windows.Interactivity
type EventToCommand() =
inherit TriggerAction<DependencyObject>()
[<DefaultValue(false)>]
static val mutable private CommandProperty:DependencyProperty
[<DefaultValue(false)>]
static val mutable private CommandParameterProperty:DependencyProperty
/// Set the command dependency property
static do
EventToCommand.CommandProperty <-
DependencyProperty.Register("Command",
typeof<ICommand>, typeof<EventToCommand>)
/// Set the command parameter dependency property
static do
EventToCommand.CommandParameterProperty <-
DependencyProperty.Register("CommandParameter",
typeof<obj>, typeof<EventToCommand>)
/// Get/Set the Command
member this.Command
with get() = this.GetValue EventToCommand.CommandProperty :?> ICommand
and set value = this.SetValue(EventToCommand.CommandProperty, value)
/// Get/Set the CommandParameter
member this.CommandParameter
with get() = this.GetValue EventToCommand.CommandParameterProperty
and set value = this.SetValue(EventToCommand.CommandParameterProperty, value)
/// Implement the Invoke method from TriggerAction to execute the command
override this.Invoke parameter =
let command = this.Command
let commandParameter = match this.CommandParameter with
| null -> parameter
| commandParam -> commandParam
if command <> null && command.CanExecute(commandParameter) then
command.Execute(commandParameter)
Here's the XAML that uses this code:
<Button Grid.Row="2" Command="{Binding ApproveExpenseReportCommand}"
Style="{StaticResource buttonStyle}" Content="Approve"
Grid.Column="1" Margin="0,10,53,0">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<Behavior:EventToCommand
Command="{Binding MouseEnterButtonCommand}"
CommandParameter="Approve" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave">
<Behavior:EventToCommand
Command="{Binding MouseLeaveButtonCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
The value converter example uses a ConverterBase class that simplifies the creation of any concrete implementations. This base class uses a combination of functional and object-oriented programming to provide a default implementation of Convert and ConvertBack. The child class can then provide a function to override the implementation of either or both of these methods. For the sake of brevity, I will not post the ConvertBase code here, but you can go to http://fssnip.net/62 to see it.
The concrete implementation that is provided as an example in these project templates is shown below:
namespace FSharpWpfMvvmTemplate.Behavior
open System
open System.Windows
open System.Windows.Data
open System.Windows.Media
open ConverterBase
/// Returns Visibility.Visible if the string is not null or empty
type StringExistsToVisibilityConverter() =
inherit ConverterBase()
let convertFunc = fun (v:obj) _ _ _ ->
match String.IsNullOrEmpty(string v) with
| false -> Visibility.Visible
| _ -> Visibility.Collapsed
:> obj
override this.Convert = convertFunc
This can be used in XAML like this:
<TextBlock Grid.Row="3" HorizontalAlignment="Center" Margin="0,10,0,0"
FontSize="12" FontWeight="Bold"
Grid.ColumnSpan="2" Text="{Binding LastApprovalDisplayMessage}"
Visibility="{Binding Path=LastApprovalDisplayMessage,
Converter={StaticResource StringExistsToVisibility}}" />
While I don't have an example in these templates of an Attached Property written in F#, it is worth noting that you can find just such an example at http://fssnip.net/69.
No comments:
Post a Comment