Skip to content

Commit

Permalink
Add Binding.subBindingSeq and SubBindings sample
Browse files Browse the repository at this point in the history
  • Loading branch information
cmeeren committed Jan 11, 2019
1 parent ea286bc commit c75cf36
Show file tree
Hide file tree
Showing 9 changed files with 392 additions and 4 deletions.
14 changes: 14 additions & 0 deletions src/Elmish.WPF.sln
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "NewWindow", "Samples\NewWin
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NewWindow.Views", "Samples\NewWindow.Views\NewWindow.Views.csproj", "{7595D7F1-5B28-415F-97C2-470A375E3BCC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SubBindings.Views", "Samples\SubBindings.Views\SubBindings.Views.csproj", "{DFAFDCF3-83E0-4440-AD8C-E45878C80F64}"
EndProject
Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "SubBindings", "Samples\SubBindings\SubBindings.fsproj", "{2946EBC5-5937-45EE-8F19-7AF0792B5A5B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -124,6 +128,14 @@ Global
{7595D7F1-5B28-415F-97C2-470A375E3BCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7595D7F1-5B28-415F-97C2-470A375E3BCC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7595D7F1-5B28-415F-97C2-470A375E3BCC}.Release|Any CPU.Build.0 = Release|Any CPU
{DFAFDCF3-83E0-4440-AD8C-E45878C80F64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DFAFDCF3-83E0-4440-AD8C-E45878C80F64}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DFAFDCF3-83E0-4440-AD8C-E45878C80F64}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DFAFDCF3-83E0-4440-AD8C-E45878C80F64}.Release|Any CPU.Build.0 = Release|Any CPU
{2946EBC5-5937-45EE-8F19-7AF0792B5A5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{2946EBC5-5937-45EE-8F19-7AF0792B5A5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2946EBC5-5937-45EE-8F19-7AF0792B5A5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2946EBC5-5937-45EE-8F19-7AF0792B5A5B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -145,6 +157,8 @@ Global
{EB80831A-431C-4CEC-AC41-8E5163E4B857} = {BBAFEB1E-93C0-4C7E-8E0A-026BB05C88EC}
{9D01D459-4EAA-446E-BC2E-F5F66D29833A} = {BBAFEB1E-93C0-4C7E-8E0A-026BB05C88EC}
{7595D7F1-5B28-415F-97C2-470A375E3BCC} = {BBAFEB1E-93C0-4C7E-8E0A-026BB05C88EC}
{DFAFDCF3-83E0-4440-AD8C-E45878C80F64} = {BBAFEB1E-93C0-4C7E-8E0A-026BB05C88EC}
{2946EBC5-5937-45EE-8F19-7AF0792B5A5B} = {BBAFEB1E-93C0-4C7E-8E0A-026BB05C88EC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3125D461-08F4-4071-AAE5-1038EF84A360}
Expand Down
55 changes: 51 additions & 4 deletions src/Elmish.WPF/Binding.fs
Original file line number Diff line number Diff line change
Expand Up @@ -280,10 +280,10 @@ module Binding =
Data = SubModelSpec (getModel >> Option.map box, getBoxedBindings, unbox >> toMsg) }

/// <summary>
/// Creates a binding to a sequence of sub-models, each uniquely identified
/// by the value returned by the getId function (as determined by the default
/// equality comparer). You typically bind this to the ItemsSource of an
/// ItemsControl, ListView, TreeView, etc.
/// Creates a binding to a sequence of sub-models/components, each uniquely
/// identified by the value returned by the getId function (as determined
/// by the default equality comparer). You typically bind this to the
/// ItemsSource of an ItemsControl, ListView, TreeView, etc.
/// </summary>
/// <param name="getModels">Gets the sub-models from the model.</param>
/// <param name="getId">Gets a unique identifier for a sub-model.</param>
Expand Down Expand Up @@ -315,3 +315,50 @@ module Binding =
getBoxedBindings,
boxedToMsg )
}



/// <summary>
/// Creates a binding to a sequence of sub-items (but not sub-components),
/// each uniquely identified by the value returned by the getId function
/// (as determined by the default equality comparer). You typically bind
/// this to the ItemsSource of an ItemsControl, ListView, TreeView, etc.
/// Analogous to a real Elm architecture, the child bindings have access to
/// the main model state along with the sub-item, and dispatch the top-level
/// message type. The model in the sub-bindings is a tuple with the main model
/// as the first element and the child item as the second element.
/// </summary>
/// <param name="getMainModel">
/// Gets the main model from the current model. This is typically 'id' when
/// called from top-level bindings, or 'fst' when called from sub-bindings
/// at any level.
/// </param>
/// <param name="getSubItems">Gets the sub-items from the current model.</param>
/// <param name="getId">Gets a unique identifier for a sub-item.</param>
/// <param name="bindings">
/// A function that returns the bindings for the sub-item.
/// </param>
/// <param name="name">The binding name.</param>
let subBindingSeq
(getMainModel: 'currentModel -> 'mainModel)
(getSubItems: 'currentModel -> #seq<'subModel>)
(getId: 'subModel -> 'id)
(bindings: unit -> BindingSpec<'mainModel * 'subModel, 'msg> list)
(name: string)
: BindingSpec<'currentModel, 'msg>
=
let getMainAndSubs currentModel =
currentModel |> getSubItems |> Seq.map (fun subModel -> getMainModel currentModel, subModel)
let getBoxedBindings () =
bindings ()
|> List.map (fun spec ->
{ Name = spec.Name; Data = BindingSpecData.box spec.Data }
)
{ Name = name
Data =
SubModelSeqSpec
( getMainAndSubs >> Seq.map box,
unbox<'mainModel * 'subModel> >> snd >> getId >> box,
getBoxedBindings,
snd >> unbox )
}
45 changes: 45 additions & 0 deletions src/Samples/SubBindings.Views/MainWindow.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<Window
x:Class="Elmish.WPF.Samples.SubBindings.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Single counter" Height="800" Width="1100"
WindowStartupLocation="CenterScreen">
<StackPanel Margin="0,20,0,10">
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Center">
<Button Command="{Binding AddCounter}" Content="Add counter" Width="150" Margin="10,0,10,20" />
<Button Command="{Binding ToggleGlobalState}" Content="Toggle global state" Width="150" Margin="10,0,10,20" />
</StackPanel>
<TreeView ItemsSource="{Binding Counters}">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding ChildCounters}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding CounterIdText}" Width="250" Margin="10,5,10,5" />
<TextBlock Text="{Binding CounterValue, StringFormat='Counter value: {0}'}" Width="100" Margin="0,5,10,5" />
<Button Command="{Binding Decrement}" Content="-" Margin="0,5,10,5" Width="30" />
<Button Command="{Binding Increment}" Content="+" Margin="0,5,10,5" Width="30" />
<Button Command="{Binding Reset}" Content="Reset" Margin="0,5,10,5" Width="50" />
<TextBlock Text="{Binding StepSize, StringFormat='Step size: {0}'}" Margin="0,5,10,5" />
<Slider Value="{Binding StepSize}" TickFrequency="1" Maximum="10" Minimum="1" IsSnapToTickEnabled="True" Width="100" Margin="0,5,10,5" />
<Button Command="{Binding AddChild}" Content="Add child" Margin="0,5,10,5" />
<Button
Command="{Binding Remove}"
Content="×" Margin="0,5,10,5" Width="20" />
<Button
Command="{Binding MoveUp}"
CommandParameter="{Binding CounterId}"
Content="" Margin="0,5,10,5" Width="20" />
<Button
Command="{Binding MoveDown}"
CommandParameter="{Binding CounterId}"
Content="" Margin="0,5,10,5" Width="20"/>
<TextBlock
Text="{Binding GlobalState, StringFormat='Global state: {0}'}"
Margin="10,5,10,5" />
</StackPanel>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</StackPanel>
</Window>
12 changes: 12 additions & 0 deletions src/Samples/SubBindings.Views/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Windows;

namespace Elmish.WPF.Samples.SubBindings
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
}
38 changes: 38 additions & 0 deletions src/Samples/SubBindings.Views/SubBindings.Views.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!-- https://stackoverflow.com/q/43693591/2978652 -->
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">

<PropertyGroup>
<LanguageTargets>$(MSBuildExtensionsPath)\$(VisualStudioVersion)\Bin\Microsoft.CSharp.targets</LanguageTargets>
<TargetFramework>net471</TargetFramework>
</PropertyGroup>

<ItemGroup>
<!-- XAML elements -->
<Page Include="**\*.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</Page>
<Compile Update="**\*.xaml.cs" SubType="Code" DependentUpon="%(Filename)" />

<!-- Recompile when XAML changed -->
<!-- https://github.com/dotnet/project-system/issues/3138#issuecomment-358355449 -->
<UpToDateCheckInput Include="**\*.xaml" />
</ItemGroup>

<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System.Xaml" />
<Reference Include="WindowsBase" />
</ItemGroup>

<!-- https://github.com/dotnet/project-system/issues/2488 -->
<Target Name="WorkaroundForXAMLIntellisenseBuildIssue" AfterTargets="_CheckCompileDesignTimePrerequisite">
<PropertyGroup>
<BuildingProject>false</BuildingProject>
</PropertyGroup>
</Target>

<Import Project="..\..\..\.paket\Paket.Restore.targets" />

</Project>
Empty file.
Loading

0 comments on commit c75cf36

Please sign in to comment.