Closed daz10000 closed 1 year ago
I don't know anything about Avalonia + WASM, but it sounds like an interesting project! It doesn't sound insane to me. Playing around with it is the best way to push the technology forward. đ
It's mind blowingly cool - I can have a friendly Xaml based UI dev process, and then target mobile, desktop, and now web with roughly the same code. The demo is easy to get going. You can just make a project with the avalonia.xplat
template here and it worked for me pretty much out of the box.
The changes I have made so far are mostly cosmetic. See below for changes and the resulting errors building. I'm just a little too unfamiliar with the avalonia ecosystem. If you feel like playing with it, I am happy to put together a quick repo. It's probably something similar. I managed to get avalonia.editor running in the browser last night which shocked me. Everything mostly just works..
Darren
$ dotnet build
MSBuild version 17.5.0-preview-23061-01+040e2a90e for .NET
Determining projects to restore...
All projects are up-to-date for restore.
Elmish.Avalonia -> C:\XXX\Elmish.Avalonia\src\Elmish.Avalonia\bin\Debug\net6.0\Elmish.Avalonia.dll
Could not extract the MVID from "obj\Debug\net7.0\refint\AvWebTest.dll". Are you sure it is a reference assembly?
AvWebTest -> C:\XXX\AvWebTestBrokenElmish\AvWebTest\bin\Debug\net7.0\AvWebTest.dll
FSC : error FS0193: The module/namespace 'Avalonia.Controls' from compilation unit 'Avalonia.Controls' did not contain the namespace, module or type 'AppBuilderBase`1' [C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\AvWebTest.Web.fsproj]
C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\Program.fs(2,14): error FS1109: A reference to the type 'Avalonia.Controls.AppBuilderBase`1' in assembly 'Avalonia.Controls' was found, but the type could not be found in that assembly [C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\AvWebTest.Web.fsproj]
FSC : error FS0193: The module/namespace 'Avalonia.Controls' from compilation unit 'Avalonia.Controls' did not contain the namespace, module or type 'AppBuilderBase`1' [C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\AvWebTest.Web.fsproj]
C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\Program.fs(3,25): error FS1109: A reference to the type 'Avalonia.Controls.AppBuilderBase`1' in assembly 'Avalonia.Controls' was found, but the type could not be found in that assembly [C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\AvWebTest.Web.fsproj]
FSC : error FS0193: The module/namespace 'Avalonia.Controls' from compilation unit 'Avalonia.Controls' did not contain the namespace, module or type 'AppBuilderBase`1' [C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\AvWebTest.Web.fsproj]
C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\Program.fs(4,18): error FS1109: A reference to the type 'Avalonia.Controls.AppBuilderBase`1' in assembly 'Avalonia.Controls' was found, but the type could not be found in that assembly [C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\AvWebTest.Web.fsproj]
C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\Program.fs(14,9): error FS0039: The value, namespace, type or module 'AppBuilder' is not defined. Maybe you want one of the following: TaskBuilder [C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\AvWebTest.Web.fsproj]
C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\Program.fs(19,9): error FS0072: Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved. [C:\XXX\AvWebTestBrokenElmish\AvWebTest.Web\AvWebTest.Web.fsproj]
Build FAILED.
diff --git a/src/Elmish.Avalonia/Command.fs b/src/Elmish.Avalonia/Command.fs
index 5cc0fc3..8713a3c 100644
--- a/src/Elmish.Avalonia/Command.fs
+++ b/src/Elmish.Avalonia/Command.fs
@@ -19,7 +19,8 @@ type internal Command(execute, canExecute) =
let mutable _handler = Unchecked.defaultof<EventHandler>
member this.AddRequeryHandler () =
let handler = EventHandler(fun _ _ -> this.RaiseCanExecuteChanged())
- CommandManager.RequerySuggested.AddHandler handler
+ // daz
+ // CommandManager.RequerySuggested.AddHandler handler
_handler <- handler
member this.RaiseCanExecuteChanged () = canExecuteChanged.Trigger(this, EventArgs.Empty)
@@ -28,4 +29,4 @@ type internal Command(execute, canExecute) =
[<CLIEvent>]
member _.CanExecuteChanged = canExecuteChanged.Publish
member _.CanExecute p = canExecute p
- member _.Execute p = execute p
\ No newline at end of file
+ member _.Execute p = execute p
diff --git a/src/Elmish.Avalonia/Elmish.Avalonia.fsproj b/src/Elmish.Avalonia/Elmish.Avalonia.fsproj
index fdbb21f..ed5f036 100644
--- a/src/Elmish.Avalonia/Elmish.Avalonia.fsproj
+++ b/src/Elmish.Avalonia/Elmish.Avalonia.fsproj
@@ -1,13 +1,11 @@
-ï»ż<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
+ï»ż<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup Condition="'$(Configuration)' != 'Debug'">
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup>
- <TargetFrameworks>net6.0-windows;netcoreapp3.1;net480</TargetFrameworks>
- <UseWpf>true</UseWpf>
- <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
+ <TargetFrameworks>net6.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<DebugType>Embedded</DebugType>
@@ -15,7 +13,6 @@
<Authors>jsacks, cmeeren, TysonMN, JordanMarr</Authors>
<Description>F# bindings for using Elmish in Avalonia</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
- <PackageProjectUrl>https://github.com/JordanMarr/Elmish.Avalonia</PackageProjectUrl>
<PackageTags>Avalonia F# fsharp Elmish Elm</PackageTags>
<!--<PackageIcon>elmish-avalonia-logo-128x128.png</PackageIcon>-->
<Version>1.0.0-alpha-2</Version>
diff --git a/src/Samples/AvaloniaExample/Program.fs b/src/Samples/AvaloniaExample/Program.fs
index ddefa40..0a185a4 100644
--- a/src/Samples/AvaloniaExample/Program.fs
+++ b/src/Samples/AvaloniaExample/Program.fs
@@ -5,10 +5,11 @@ open Avalonia
open AvaloniaExample
open Elmish.Avalonia.AppBuilder
+
module Program =
@@ -18,3 +19,6 @@ module Program =
[<EntryPoint; STAThread>]
let main argv =
buildAvaloniaApp().StartWithClassicDesktopLifetime(argv)
If you can create a repo that would make it super easy for me to try it out. Also, I know @AngelMunoz is interested in Avalonia + WASM as well.
~I had the web templates working at some point~, take a look at https://github.com/AvaloniaUI/avalonia-dotnet-templates/pull/102 ~It should give you an idea how to set up even with funcui~
EDIT: I thought this was a notification in the FuncUI repo (I'll have to pay more attention when reading notifications from the phone)
I agree with Jordan a sample repository would be very helpful and I could lend a hand if there are other issues, over all Avalonia works just nicely with WASM workloads, in the PR I linked above it shows at least what dependencies and which versions of the packages we used to make funcui work, since there's no funcui here it should be as simple or even simpler to get it working if we part from there
I'd suggest you can start with a simple counter and then move from there so we can identify missing APIs (like the one you mentioned)
Take a look at this - it has a small hack to the Elmish.Avalonia
repo mainly to get it to compile with the missing api, and then a fairly out of the box avalonia cross platform template. I'm sure it's something pretty simple (and dumb) but any help appreciated. I don't know if removing the call I removed is critical for example :(
https://github.com/daz10000/ElmishAvaloniaExample
I have a fairly similar dummy app working with plaIn MVVM successfully if you want to compare.
I even have CI working on the repo, so it reliably (doesn't build) the way it's not building for me. Thanks in advance for taking a look
e.g.
https://github.com/daz10000/ElmishAvaloniaExample/actions/runs/4350930131
I saw your FuncUI posts too @AngelMunoz - I will check those out as well. I'm mainly looking for an F# idiomatic way of getting Avalonia working in the web space, and just a little too worn out by the endless models and views and viewmodels of the MVVM world - "it should have been an function call" would be my high level review.
@daz10000 I managed to update the template from that FuncUI post to Elmish.Avalonia
https://github.com/AngelMunoz/AvaloniaTestElmish
However, I'm facing a weird build bug in the wasm target.
PS C:\Users\scyth\repos\AvaloniaTestElmish> dotnet run --project AvaloniaTest.Web
Building...
A fatal error was encountered. The library 'hostpolicy.dll' required to execute the application was not found in 'C:\Users\scyth\repos\AvaloniaTestElmish\AvaloniaTest.Web\bin\Debug\net7.0\'.
Failed to run as a self-contained app.
- The application was run as a self-contained app because 'C:\Users\scyth\repos\AvaloniaTestElmish\AvaloniaTest.Web\bin\Debug\net7.0\AvaloniaTest.Web.runtimeconfig.json' was not found.
- If this should be a framework-dependent app, add the 'C:\Users\scyth\repos\AvaloniaTestElmish\AvaloniaTest.Web\bin\Debug\net7.0\AvaloniaTest.Web.runtimeconfig.json' file and specify the appropriate framework.
PS C:\Users\scyth\repos\AvaloniaTestElmish>
I'm not sure if I'm missing something or am I configuring something wrong....
Besides that I tested that template with the desktop target, and it ran completely fine I'm sure once that wasm issue gets away (which I have no idea how to fix) you should be use those as a starter for dotnet templates with Elmish.Avalonia
nice! - that's progress. Let me pull your fork and see if I can reproduce that. I have a parallel code base that's similar and built off the MVVM template so maybe I can compare and work out what's happening.
Edit: - does reproduce. Let me try some diffs with a working build.
I can get it to compile and run with just this change to AvaloniaTest.Web.fsproj
. I get just a blank screen after it finishes loading, but that's kind of progress
-ï»ż<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
+ï»ż<Project Sdk="Microsoft.NET.Sdk">
Debugging - it does start up, code runs, seems to complete initialization properly, but nothing getting to screen and might still be failing somewhere. Desktop works. Well down to print statement debugging but the problem seems to be that the top level objects in MainViewModel
and CounterViewModel
aren't getting executed, so designVM
, vm
, aren't initialized. Not sure if that's a wasm implementation thing, or if an error is getting thrown somewhere I can't see and initialization stops.
Progress!
The App OnFrameworkInitializationCompleted
needs a case for SingleViewApplicationLifetime
- the desktop MainView
branch doesn't apply. This gets me to at least a rendered screen but buttons still not working.
override this.OnFrameworkInitializationCompleted() =
printfn "App.OnFrameworkInit top"
match this.ApplicationLifetime with
| :? IClassicDesktopStyleApplicationLifetime as desktop ->
printfn "App.OnFrameworkInit classic view"
let view = MainView()
printfn "App.OnFrameworkInit got view"
desktop.MainWindow <- view
printfn "App.OnFrameworkInit starting"
try
ViewModels.MainViewModel.vm.Start(view)
with x ->
printfn $"Exception: {x.Message} \n {x.StackTrace}"
printfn "App.OnFrameworkInit started"
| :? ISingleViewApplicationLifetime as singleViewLifetime ->
printfn "App.OnFrameworkInit single view lifetime"
printfn "App.OnFrameworkInit set mainview"
singleViewLifetime.MainView <- CounterView()
printfn "App.OnFrameworkInit get vm y"
let y = ViewModels.CounterViewModel.vm
printfn "App.OnFrameworkInit get vm x"
let x = ViewModels.MainViewModel.vm
printfn "App.OnFrameworkInit start vm"
x.Start(singleViewLifetime.MainView)
printfn "App.OnFrameworkInit done"
Well, after banging head against this for quite a while, I'm stuck. It does seem to initialize everything but the controls that have bindings (count, and the datatable) never appear, From the logging (I learned how to use that at least), there is a lot of activity initializing and drawing them, but no data ever appears and the buttons are not active. Probably something simple but I can't see it right now My hacked version of your repo @AngelMunoz is here. @JordanMarr - the underlying library looks beautiful and I'm soo close to getting it working for wasm, I want to keep grinding away at this. One thing I could never see (in the desktop or web versions) was any of the binding events in the logging. I put some print statements in the binding functions and they do get called on both platforms. Just nothing appearing for the web. The biggest difference between web and desktop is the main window. The web doesn't really have concept of windows in general, so MainView is just a container for the single CounterView in Angel's example
Nice! This is what I love about OSS. Edit: I just saw your last post. đ
It could be something related to trimmed assemblies, both android and wasm do that so we might be trimming something without knowing (like the data grid assembly for example)
Because if it works for desktop it should work in the other platforms as well, I'll keep taking a look during the week or the next weekend and let you know if I figure out something
Yeah, I think it's very close - I wonder if there is something dumb in there, like a control not enabled by default in the wasm world. The wasm and desktop code is almost the same, just slightly different initialization and the focus on the actual control being center stage, not the windows as containers. Darker theory - something going wrong during the binding setup that's throwing an error not caught. It's tricky to catch errors - they don't go to stdout by default. I turned on every logging feature I could find and wrapped a bunch of stuff in try/except handlers.
As you just wrote @AngelMunoz - could easily be a missing assembly or something needed at runtime. From the logging, all the interactions with the controls are there. It talks to the dataview etc, measures everything and lays it out (per the logs), but just doesn't display it finally (maybe hiding it because there is no data?) Logs attached
A hell of a lot of print statements later, and comparing the startup of the desktop and web versions, I haven't resolved the problem, but have narrowed it down. TheViewLocator
build code never fires in the web version for COunterView. I can't tell if this is the root cause or just related to the counter view not fulling rendering or being responsive. Currently trying to understand how this code gets executed (it works in the desktop build). XXX bits are all my tracing. I suspect root cause is still that for web, we initialize as a singleview application and so I'm skipping creating the mainview (because it's window derived). I might need to restruct the app (this is your test app @AngelMunoz ) so the main "window" is a usercontrol or something for the web.
Retrying the path where I try to make MainWindow
the MainViewModel
and it (rightfully!) doesn't want to create a window when it's running in the browser
Exception: Specified method is not supported. [dotnet.js:2165:16](http://localhost:7000/dotnet.js)
at Avalonia.Browser.BrowserWindowingPlatform.CreateWindow() in /_/src/Browser/Avalonia.Browser/WindowingPlatform.cs:line 17 [dotnet.js:2165:16](http://localhost:7000/dotnet.js)
at Avalonia.Controls.Platform.PlatformManager.CreateWindow() in /_/src/Avalonia.Controls/Platform/PlatformManager.cs:line 31 [dotnet.js:2165:16](http://localhost:7000/dotnet.js)
at Avalonia.Controls.Window..ctor() in /_/src/Avalonia.Controls/Window.cs:line 219 [dotnet.js:2165:16](http://localhost:7000/dotnet.js)
at AvaloniaTest.Views.MainView..ctor() in .../AvaloniaTest\Views\MainView.axaml.fs:line 8 [dotnet.js:2165:16](http://localhost:7000/dotnet.js)
at AvaloniaTest.App.OnFrameworkInitializationCompleted() in .../AvaloniaTest\App.axaml.fs:line 40
Can you ditch the view locator and manually bind the VM?
WOO! - finally, success. So, (unfortunately but logically), the main "window" has to be a usercontrol for the web version. No windows. If I change MainWindow
in @AngelMunoz 's AvaloniaTest app to a UserControl
, you have to lose a bunch of properties - like icon and title that aren't relevant for a usercontrol. The App.axaml.fs
branch for desktop won't work now, since it needs a window, but commenting that out, I can get the web version to start and work!
It seems like a cross platform application will need two different top level contains - a MainWindow for desktop and a MainControl for all the other SingleViewLifetime applications. I'll see if I can get both to coexist but do you have a cleaner solution here?
Ah Yeah the window thing makes sense, with Avalonia.FuncUI we actually provide a Control to the single view lifetime, so perhaps here we need to do the equivalent
EDIT: Just as I was typing this you made it work
This is the App startup code with the two branches for Desktop (now broken) and Web (now working)
type App() =
inherit Application()
override this.Initialize() =
// Initialize Avalonia controls from NuGet packages:
printfn "App.Initialize top"
let _ = typeof<Avalonia.Controls.DataGrid>
printfn "App.Initialize loading"
AvaloniaXamlLoader.Load(this)
printfn "App.Initialize loaded"
override this.OnFrameworkInitializationCompleted() =
printfn "App.OnFrameworkInit top"
match this.ApplicationLifetime with
| :? IClassicDesktopStyleApplicationLifetime as desktop ->
printfn "App.OnFrameworkInit classic view"
let view = MainView()
printfn "App.OnFrameworkInit got view"
// HACKHACK - commented out since this won't work for a usercontrol
// desktop.MainWindow <- view
printfn "App.OnFrameworkInit starting"
try
ViewModels.MainViewModel.vm.Start(view)
with x ->
printfn $"Exception: {x.Message} \n {x.StackTrace}"
printfn "App.OnFrameworkInit started"
| :? ISingleViewApplicationLifetime as singleViewLifetime ->
try
printfn "App.OnFrameworkInit single view lifetime"
printfn "App.OnFrameworkInit set mainview"
let view = MainView()
singleViewLifetime.MainView <- view
let x = ViewModels.MainViewModel.vm
printfn "App.OnFrameworkInit start vm"
x.Start(view)
printfn "App.OnFrameworkInit done"
with x ->
printfn $"Exception: {x.Message} \n {x.StackTrace}"
| _ ->
// leave this here for design view re-renders
printfn "App.OnFrameworkInit other view"
printfn "App.OnFrameworkInit mark completed"
base.OnFrameworkInitializationCompleted()
printfn "App.OnFrameworkInit done"
Yeah looks like there has to be a way to use a "content" control for the window or the control itself
For example in the FuncUI templates we do this https://github.com/AngelMunoz/AvaloniaTest/blob/main/AvaloniaTest/Program.fs#L22-L27
match this.ApplicationLifetime with
| :? IClassicDesktopStyleApplicationLifetime as desktopLifetime ->
desktopLifetime.MainWindow <- MainWindow()
| :? ISingleViewApplicationLifetime as singleViewLifetime ->
singleViewLifetime.MainView <- Counter.view()
| _ -> ()
where MainWindow
is actually a Window
type with the content set to the control this.Content <- Counter.view()
and in the single lifetime we pass the Counter.view()
control directly
Thanks again for the help, code and just listening to me complain :) It's a little kludgey but I ended up adding a MainView and MainWindow for the two cases. I figure since the desktop version can optionally style icons and titles, it deserves a separate top container anyway. I think I can get back to building an actual app now. The final code (modified version of your demo @AngelMunoz ) is here. If you want to sell me on using FuncUI, I'm open to giving that a try too. I am looking for a relatively simple way to stick to a mostly Elmish pattern for UI building - I've had great experiences maintaining a lot of code with react that way, and it feels like the right pattern for Avalonia, but I'd rather work out the right pattern before diving into writing something large. I'll probably continue to experiment a little. Thanks again, and especially @JordanMarr for putting Elmish.Avalonia out there. Let me know if I can be helpful - it would be nice to have a template that does cross platform out of the box.
itâs super exciting that you got it working and can now continue on to creating an app!
I think it would be a great idea to have it listed in the Samples folder here in the repo, so feel free to submit a PR. Iâm sure others would be very interested to benefit from the hard work you guys did to get it working!
As for FuncUI, i would imagine that you should be able to have a hybrid approach where some views are xaml and some are FuncUI. (Iâve been meaning to try that but havenât gotten around to it yet.)
The main advantage to using xaml is that it lets you take advantage of the fantastic xaml preview extension and the designVM
.
Otoh, the FuncUI style is a lot of fun to use.
very happy to submit as a sample. I was thinking you could use some more.  speaking of which, Iâm looking for the idiomatic way to get a child component to message the main view to switch views. I have an application with a bunch of distinct models that need to switch back and forth (eg a gallery view then an editor for items on gallery).  Was trying to work out if having main model subscribe to child events was the recommended model ?  suggestions apprecursed and Ill get you a PR with the exampleDarrenAm 3/18/23 um 7:21 PM schrieb Jordan Marr @.***>:ï»ż itâs super exciting that you got it working and can now continue on to creating an app! I think it would be a great idea to have it listed in the Samples folder here in the repo, so feel free to submit a PR. Iâm sure others would be very interested to benefit from the hard work you guys did to get it working! As for FuncUI, i would imagine that you should be able to have a hybrid approach where some views are xaml and some are FuncUI. (Iâve been meaning to try that but havenât gotten around to it yet.) The main advantage to using xaml is that it lets you take advantage of the fantastic xaml preview extension and the designVM. Otoh, the FuncUI style is a lot of fun to use.
âReply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: @.***>
@daz10000 oh no worries I'm not trying to sell FuncUI here, I just grab it as a reference because that's the one I know it works and have a little bit of experience with.
I'm glad everything is working now, I'm sure there's folks in the community who also like this approach and would like to use it as well!
Iâm looking for the idiomatic way to get a child component to message the main view to switch views. I have an application with a bunch of distinct models that need to switch back and forth (eg a gallery view then an editor for items on gallery). Â Was trying to work out if having main model subscribe to child events was the recommended model ? Â
Are you doing it old school style where you are opening edit views in their own separate Window with their own Elmish loop, or are you doing it more like a SPA where your views are in user controls that are controlled from the main shell view?
Assuming the latter, the Elmish.WPF Samples have some good examples on how to wire up submodel views. There are some really cool abstractions they made (that were copied into this library) that makes it easier to wire up the submodels.
If the former, i think it wouldnât be cool to use Rx to send a message from one window to another, and you could pipe those in using the Elmish 4 event subscriptions!
I havenât embarked on either of those journeys just yet so open to recommendations.  My main use case is web based so no multiple windows , just none area.  I would prefer to minimally entangle the pieces (not embedding lower component models in the main model and running all the events through a single dispatcher ) but as a practical matter when the user finishes a subtask the child user control needs to let a parent know so the view can switch.  I did notice that youâve modeled the elmish.wpf functions and they have good docs so thatâs helpful. If there is a simple example of child user control messaging a parent that would be helpful. i see support for opening mew âwindowsâ and managing the transition back but in the web and mobile cases there are no windows. darrenAm 3/18/23 um 9:58 PM schrieb Jordan Marr @.***>:ï»ż
Iâm looking for the idiomatic way to get a child component to message the main view to switch views. I have an application with a bunch of distinct models that need to switch back and forth (eg a gallery view then an editor for items on gallery). Â Was trying to work out if having main model subscribe to child events was the recommended model ? Â
Are you doing it old school style where you are opening edit views in their own separate Window with their own Elmish loop, or are you doing it more like a SPA where you are views in user controls that are controlled from the main shell view? Assuming the latter, the Elmish.WPF Samples have some good examples on how to wire up submodel views. There are some really cool abstractions they made (that were copied into this library) that makes it easier to wire up the submodels. If the former, i think it wouldnât be cool to use Rx to send a message from one window to another, and you could pipe those in using the Elmish 4 event subscriptions!
âReply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: @.***>
I updated the AvaloniaExample project with the following:
IStart
/ Start
to IElmishViewModel
/ ElmishViewModel
, which has method StartElmishLoop
. (I think this is way more intuitive)AboutView
/ AboutViewModel
MainView
that swap out the contentMessaging
module that uses Rx to provide pub/sub between view modelsAboutViewModel
now publishes a GoHome
message when the Ok
button is clickedMainViewModel
now subscribes to this event via an Elmish subscriptionooh! thank you. make my Sunday.  will check this out when I have better network connection and try to follow the pattern in the counter app. that sounds like exactly what I need.  Am 3/19/23 um 11:36 AM schrieb Jordan Marr @.***>:ï»ż I updated the AvaloniaExample project with the following:
Renamed IStart / Start to IElmishViewModel / ElmishViewModel, which has method StartElmishLoop. (I think this is way more intuitive) Added a second view, AboutView / AboutViewModel Added nav buttons to the MainView that swap out the content Added a Messaging module that uses Rx to provide pub/sub between view models AboutViewModel now publishes a GoHome message when the Ok button is clicked MainViewModel now subscribes to this event via an Elmish subscription
âReply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you were mentioned.Message ID: @.***>
You should have a PR now with the cross platform example all cleaned up. I can confirm that I was able to easily wire your view swapping solution into the app I'm building and it works like a charm. I also love being able to test the application quickly with desktop with all the simplicity that it gives, and then just build the wasm/web version and see it run the same. It's really quite stunning (the web version is maybe a little slower with event handling but still quite usable). This looks like it will be very productive.
Merged!
A more declarative way of handling navigation would be to use the TabControl with a tab for each page.
Or, if you want to stick with using buttons to do it manually, I was messing around with styling the buttons in the MainView to look more like a tab bar in the sample app:
Btw, I think it's really amazing that the Avalonia preview pane extension allows you to interact with the form in design mode. For example, I can actually click on the +/- buttons and the form will actually work. đ„
Aside: and I mentioned this in the other issue I just filed.. The TabControl might be a nice way to evolve this sample into a gallery showing off the different controls. I loved the early Silverlight demo that exercised everything and it was a great resource for implementation because you could copy working examples. It's either a gallery or I try to write a useful demo piece of software as my next sample, like a calendar , todo list... or something else. Happy to write down my notes on using Elmish.Avalonia here as documentation in samples. Everything else is going well with my real app.
I know this is slightly insane given that this is already pushing the envelope, but I like the Elmish pattern and was trying to retrofit this onto the Avalonia Web demo. I ran into obvious problems (build targets) that were fixable and less obvious issues like missing apis
CommandManager.RequerySuggested.AddHandler handler
. I don't have it working but before I dig further, is this just an insane thing to try, or should it work with a bit more tweaking? (pointers appreciated and happy to share what I've had to change so far)