Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Discussion: X# / Xaml Sharp / Xaml Code - inspired by SwiftUI #804

Closed
mdtauk opened this issue Jun 4, 2019 · 78 comments
Closed

Discussion: X# / Xaml Sharp / Xaml Code - inspired by SwiftUI #804

mdtauk opened this issue Jun 4, 2019 · 78 comments

Comments

@mdtauk
Copy link
Contributor

mdtauk commented Jun 4, 2019

Apple announced SwiftUI which replaces an older and much more verbose method of building UI for their iOS, iPadOS and macOS platforms.

image

This is not something that could be done by time of WinUI 3.0 and so is not a proposal per se, but XAML being XML based, is nothing if not verbose. A lot of effort has been made in recent years to make it possible to write less Xaml to do more. VisualStateTriggers being a massive one replacing the VisualStateManager. There is also a proposal to re-work the Grid panel control, to make it more powerful with less Xaml required.

XamlDirect currently exists aimed at middleware tools which can generate XAML from code, but is there some merit into looking at what SwiftUI is doing to perhaps create an alternative to Xaml Markup, with the same power and flexibility of Xaml, but similar to React Native, providing a less verbose version of Xaml.

What it could be called is anyone's guess - for the sake of this suggestion I call it X#, XamlSharp (perhaps inspired by C#'s use of the dot property syntax)

using xaml;  
  
xaml page  
{  
      this.backgroundColor = themeResource(ApplicationPageBackgroundColor);  
      this.foregroundColor = themeResource(ApplicationTextForegroundColor);  
  
      xaml grid[name "rootGrid", rows "*, *, *, Auto, 12epx"]  
      {  
            xaml stackPanel[name "toolbar", orientation Horizontal]  
            {}  
            xaml button[grid.row "4" content xaml bind(_appIcon)];  
      }  
}  

^ Example code is not a suggested syntax, but just an illustrative example

This is a place where anyone who has an interest in simplifying Xaml can share their thoughts, ideas, syntax suggestions

@mdtauk mdtauk added the feature proposal New feature proposal label Jun 4, 2019
@msft-github-bot msft-github-bot added this to Freezer in Feature tracking Jun 4, 2019
@msft-github-bot msft-github-bot added this to Needs triage in Controls Triage Jun 4, 2019
@jevansaks jevansaks added the discussion General discussion label Jun 5, 2019
@RichiCoder1
Copy link

RichiCoder1 commented Jun 5, 2019

Adding Ammy UI (http://www.ammyui.com/) as excellent prior art in this area.

If this is something that moved forward, it'd also be great if said code or DSL made doing styles & visual state management CSS levels of easy.

@mdtauk
Copy link
Contributor Author

mdtauk commented Jun 5, 2019

image
Ammy is a good attempt at making XAML UI simpler, but it does lean too much towards CSS than more familiar code based approaches that may be more familiar to Microsoft developers, and would work more seamlessly with current tooling I would expect.

image
Example from http://www.geldesk.org/

JSON is very popular at the moment, but it is so fickle and easy to break - where as XML is robust but complex and wordy.

Whatever format is chosen, there should be a thought on constructing the UI on the screen decoratively, but an ability to easily manage Templates and Styles either inline or as attached files. At the moment XAML does it all, but it is bothersome to edit for designers, and also verbose for those who prefer to work in code.

@contextfree
Copy link

It's already possible to make WPF or WinUI UI purely in code (for example, Charles Petzold's WPF book didn't even introduce XAML at all until halfway through the book) so it might be good to use this issue to call out specific problems with doing this today (bindings and templates for example?)

It also might be worth looking at Fabulous which is an existing project for F# and WPF or Xamarin.Forms that seems along the lines suggested in this topic.

@mdtauk
Copy link
Contributor Author

mdtauk commented Jun 5, 2019

It's already possible to make WPF or WinUI UI purely in code (for example, Charles Petzold's WPF book didn't even introduce XAML at all until halfway through the book) so it might be good to use this issue to call out specific problems with doing this today (bindings and templates for example?)

The thing that makes SwiftUI stand out is that it remains declarative in nature, similar to HTML and Markup, but is within the language and syntax of Swift. It is possible to create XAML objects, but the concept of nesting elements, and declaring the properties, bindings, templates and styles are obtuse and not very effective.

@Felix-Dev
Copy link
Contributor

Felix-Dev commented Jun 5, 2019

I guess it will come down to available resources at Microsoft. For the forseeable future, I want them to first-and-foremost focus on making XAML less verbose - and there have been countless of proposals over the years how to do just that. WinUI 3.0 is currently blocking most of that work so we need to wait some more months until MS and the community can work together and give XAML a much needed update across the board. Depending on how that will go, we can re-visit your idea, Martin, and potentially look at areas outside of XAML markup to make UI design more efficient.

@Happypig375
Copy link

@mdtauk
That looks awfully similar to what we can do today:

using System;
using Windows.ApplicationModel.Activation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
namespace NoXaml
{
    static class Program { public static void Main(string[] _) => Application.Start(p => new MyApp()); }
    class MyApp : Application
    {
        protected override void OnLaunched(LaunchActivatedEventArgs args)
        {
            Window.Current.Content = MainPage;
            Window.Current.Activate();
        }

        UIElement MainPage =>
            new Grid
            {
                Background = new SolidColorBrush(Colors.Blue),
                Children = {
                    new Button { Content = "Hello!" }
                }
            };
    }
}

@Mike-E-angelo
Copy link

Mike-E-angelo commented Jun 5, 2019

Adding @VincentH-Net's CSharpForMarkup to the mix as well for reference. https://github.com/VincentH-Net/CSharpForMarkup

FWIW, ATM I think any idea that circumvents a visual designer is a terrible idea but I am keeping an open mind about it. Maybe it will grow on me. 😁

Whatever format is chosen

Ideally, you should be able to choose between the two (or more) formats, for optimal adoption. This is the forward-thinking and .NET-like approach that @cwensley utilizes for his ETO project: https://github.com/picoe/Eto

@dpierangeli
Copy link

Ok, it can be an useful addition, but please don't do this:

swiftuiblah

A declarative UI definition should not be mixed with application logic (my idea).

@maxkatz6
Copy link
Contributor

maxkatz6 commented Jun 5, 2019

Avalonia team also discussed about XAML markup alternative:
AvaloniaUI/Avalonia#2502

@TonyHenrique
Copy link

TonyHenrique commented Jun 5, 2019

XAML markup is a advancement. These approaches are limited. .NET and XAML need to move forward and reach those platforms, not the contrary.
XAML is a way to instantiate objects and separate 'UI code' from the 'code behind'.

Also give a look at #740 (comment)

@TonyHenrique
Copy link

TonyHenrique commented Jun 5, 2019

If we look carefully we see clearly the simplicity and advantages of XAML.
If XAML runs everywhere, it could be used instead of HTML in lots of use cases.
We need to be careful to don't waste time with these pseudo improvements, as some folks may up ending wanting to describe UI using YAML files or JSON...

@weitzhandler
Copy link
Contributor

weitzhandler commented Jun 5, 2019

@mdtauk
My 2 cents:
I'm happy with XAML the way it is, they should just add plenty of more built-in converters, interactivity actions and markup extensions, an integrated way of C# expressions, and a lot of syntax-sugars to make things less-verbose.
But if we're to replace XAML, it's for the favor of a C#-only Dart/Flutter/Razor-like UI. No new languages please. In this case, the WinUI team should work closely with the C# team to see how we can introduce syntactic-sugars to make UI declaration easy and less verbose in C#, as well as rendering, hot load, code generation and previewing.

@Felix-Dev
Copy link
Contributor

There are definitely a lot of possible XAML Markup improvements the team should focus on before thinking about alternative ways to build a UI. Both on the control level (like the new grid proposal) and the XAML language itself like introducing a negation syntax for binding, i.e:
IsVisible = "{x:Bind !SomeObject.SomeProperty}"
or stuff mentioned in these proposals: #62 and dotnet/wpf#480 (and there are a ton more)

To sum it up: The focus should be first-and-foremost on improving XAML markup!

@mdtauk
Copy link
Contributor Author

mdtauk commented Jun 5, 2019

Offering the choice of building XAML UI in C#, C++, F#, VB, JSON, as well as Xaml markup itself - would allow the developer to choose what way is best for them - as long as it all renders the same.

There is Xaml Direct Microsoft.UI.Xaml.Core.Direct but it is intended for middle-ware tools, is very low level, and hasn't been formalised as a first class way to build an app's UI. (New Project templates, sample code, etc)

I am not averse to Xaml as Markup (but anything that results in less markup and simpler declarations would be welcome) but SwiftUI shows that there are alternatives. No idea if one is better than the other, but it is interesting to discuss the pain points, the aspirations, and to possibly learn lessons from other platform ideas :)

@RyoukoKonpaku
Copy link

RyoukoKonpaku commented Jun 5, 2019

I do agree with the rest that XAML improvements are of priority first and foremost.

For the sake of discussion on possible alternatives how about talking with the Razor Compiler team? They seem to have a decent compiler already that can parse C# and VB (not too sure if this is still supported on newer razor) expressions in HTML and instantiating C# classes (Blazor Components in this case). It's HTML is actually more like XML as well since Razor is kinda strict with closing tags for their compiler which makes it a good candidate for an alternative. Plus points since it's also an MS product so they can freely communicate between the two if necessary.

Off the top of my head it'd probably be like this? This is assuming we treat Xaml classes as Blazor components so that there's less effort needed to make it work.

@* .csxaml additional code can be done on code-behind .cs or even @code section on razor if supported on this .csxaml *@
<Grid>
    @* Using the new directive support that .razor has *@
    <Grid.Row @Bind:Height="someHeightVariable"
                      @Bind:Mode="Binding.TwoWay">
         <Grid.Column>
             @* Can use lambda or for MVVM be a method on the ViewModel *@
             <Button PlaceHolder="Todo" 
                           @Command="ViewModel.SomeMethod"
                           @Background="ConstantsClass.SomeBrush">
                   Some Button
             </Button>
         </Grid.Column>
    </Grid.Row>
</Grid>

This should be less effort in my opinion that writing a new DSL parser from scratch, but the downside is the razor compiler is biased to C# by default so adding other languages like F# might be a hassle.

@Mike-E-angelo
Copy link

I like your thinking @RyoukoKonpaku. Unfortunately, Razor is a templating engine, and the results it generates is a plain text file (or stream) for use to emit to a browser. What we're attempting to do here is describe an object graph that ultimately gets loaded into memory and rendered from there.

For instance, while you do reference a Grid object, there is no way for Razor to know what exactly that is, so there is no way to load it into memory for further processing.

Unless, of course, you're suggesting that we use Razor to create XAML files and then from there we load in the Xaml, which would work. In that case, however, you're doubling the required components to get the view loaded, plus there are other considerations such as debugging. How do you debug a binding that was defined in a template file that created the Xaml file?

Not to say that it wouldn't work. It's a neat idea, but it would be an involved undertaking, IMO.

@mdtauk
Copy link
Contributor Author

mdtauk commented Jun 5, 2019

One point I think most of us would agree on, is that whatever emerges should be Human Readable

@TonyHenrique
Copy link

TonyHenrique commented Jun 5, 2019

I would add that I feel that if we unite and ask for the XAML Standard or a Universal XAML, it would be much better that any attempt to change or improve the XAML.

About the code only approach, the best to do would be invest in F# elmish style and also gjallahorn with a WinUI XAML Type Provider.

Another thing that could be done is to allow XAML literals in C#/F# code.
This would enable code like this

let myButton title = <Button Text=title />

@RyoukoKonpaku
Copy link

RyoukoKonpaku commented Jun 5, 2019

@Mike-EEE Indeed it's not that smooth sailing either. I'm actually referring to Blazor in this case which can detect C# classes as Components in Blazor terms. The .razor file actually compiles into a render instruction set on a class. So I'd assume it's possible to change the generated class from the AST that Razor parses.

@using NameSpace.SomeControls
@inject ViewModel VM


@* SampleComponent.razor *@
<ChildComponent>
    <NestedComponent />
</ChildComponent>

The generated class is this.

// compiled SampleComponent.g.cs
using NameSpace.SomeControls;
# alot of pragmas here since it's generated
public partial class SampleComponent : Microsoft.AspNetCore.Components.ComponentBase
{
    [Inject]
    protected ViewModel VM { get; set; }

    protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) {
        builder.OpenComponent<Namespace.ChildComponent>();
        builder.OpenComponent<Namespace.NestedComponent>();
        builder.CloseComponent<Namespace.NestedComponent>();
        builder.CloseComponent<Namespace.ChildComponent>();
        // ... removed for brevity but basically constructs the combination of 
        // strings (e.g. div, span etc...) and Component which are eseentially just classes
    }
}

So what I'd imagine is that we replace the generated builder into a series of Xaml class instantiations into an object graph via Xaml.Direct middleware. Also remove the ability to use html tags so it does not compile for that.

So from the above it would compile to something like this

// SampleComponent.g.cs
using NameSpace.SomeControls;
# pragmas here
public partial class SampleComponent: Microsoft.UI.Xaml.UserControl
{
    [Inject]
    protected ViewModel VM { get; set; }

    protected Microsoft.UI.Xaml.UserControl BuildObjectGraph() {;
         // Create object graph here for ChildComponent and it's nested Control.
    }
}

Essentially the effort needed here is the generation from razor generated AST to XAML.Direct instructions to construct the Object Graph.

@Mike-E-angelo
Copy link

To be sure, @RyoukoKonpaku, are ChildComponent and NestedComponent in NameSpace.SomeControls or Namespace ? My Razor/Blazor is rather newb, so I am trying to understand how it is resolving those.

In either case, that does look interesting and worth an exploration, IMO. 👍

@reli-msft
Copy link

I think this could be discussed in https://github.com/dotnet/csharplang?
It is all about extending C# to provide ability to define embedded DSLs, then you can have a UI DSL and other DSL if you need.

@RyoukoKonpaku
Copy link

@Mike-EEE yep ChildComponent and NestedComponent are C# classes that derives from ComponentBase on the NameSpace.SomeControl namespace, I kinda flunked the example abit there but it should have referenced NameSpace.SomeControls.ChildComponent on the generated class instead of NameSpace.ChildComponent.

You can also refer the full namespace to reference a Component just like how you'd reference a normal class.

<NameSpace.SomeControls.ChildComponent>
    <NameSpace.SomeControls.NestedComponent />
</NameSpace.SomeControls.ChildComponent>

The AST to C# class is the bigger effort if this was to be done from what I can tell but it's definitely plausible with the tools available now, Xaml.Direct, Razor's AST, and knowledge on gluing those together, razor bits from the Razor compiler team and Xaml.Direct usage from the WinUI team.

@Mike-E-angelo
Copy link

You might be onto something @RyoukoKonpaku. I'm taking @reli-msft's hint and moving this onto a perhaps more pertinent forum: dotnet/aspnetcore#10911

See you there. :)

@jevansaks jevansaks moved this from Needs triage to Backlog in Controls Triage Jun 6, 2019
@VincentH-Net
Copy link

VincentH-Net commented Sep 19, 2019

@Odonno Glad to hear you like it!

Do you think CSharpForMarkup can work with UWP?

Yes, the approach I took with CSharpForMarkup for Xamarin Forms can be applied to any .NET UI framework that uses data binding.

Since CSharpForMarkup is just a thin set of helper functions directly on top of the UI framework, you could effectively create a close lookalike of these helpers for UWP. Some helpers for Forms are specific but most will have a close equivalent on UWP.

You're welcome to do a PR to add a UWP port on CSharpForMarkup :-)
Simply copy XamarinFormsMarkupExtensions.cs
to UwpMarkupExtensions.cs and refactor it to UWP.

You might want to consider porting your UWP sample to UNO since that virtually is 1 on 1 compatible with UWP. Now that is a PR I'd really love to see :-)

@Odonno
Copy link

Odonno commented Sep 19, 2019

@VincentH-Net Good to know. I'll give a look at it once the 3.0 of ReduxSimple is finished.

@charlesroddie
Copy link

charlesroddie commented Sep 21, 2019

UI defined in code can achieve the following now:

  • Similar hierarchical structure to XAML
  • Type safety of setting properties, unlike XAML which uses various string names and conversions
  • Type safety of bindings, by avoiding existing WPF/UWP/Xamarin untyped bindings
  • No need to define bindable properties any more, only standard settable properties
  • Binding sources can be much more flexible using a typed reactive approach
  • Functions that are easy to defined and accessed as objects rather than by name lookup, and much easier to work with than converters.

For example we can already write:

// in a ViewModel
let text = Mutable.create ""
let capitalizedText = text |> Signal.map (fun s -> s.ToUpper())
let add() = text.Value <- text.Value + "a"

// in a View
let label = Label()
capitalizedText.bind label.set_Text
StackLayout(
    Views = [
        label
        Button(Text = "+A", Click = add)
        ]
    )

Useful future tooling:

  • A form of live views and/or hot reload, including a mechanism for sample data. For example:
type FooLabel(bar:string) =
    inherit Label(Text = "foo"+bar)
    [<Preview>] // only used for live preview tooling
    static member Sample = FooLabel("bar")

@surfsky
Copy link

surfsky commented Apr 3, 2020

I like QML & Razor synax:

@UserControl
@Class ControlCatalog.Pages.ButtonPage
@Using System.Drawing

StackPanel {
    Orientation:"Vertical" 
    Spacing:"4"
    TextBlock{Classes:"h1" Text:"Button"}
    TextBlock{Classes:"h2" Text:"A button control"}
    StackPanel{
        Orientation:"Horizontal"
        Margin:"0,16,0,0"
        HorizontalAlignment:"Center"
        Spacing:"16"
        StackPanel{
            Orientation:"Vertical" Spacing:"8" Width:"150"
            Button{Text: "Button"}
            Button{Foreground:"White" Text:"Foreground"}
            Button{Background:"@ThemeAccentBrush" Text:"Background"}
            Button{IsEnabled:"False" Text:"Disabled"}
            Button{
                Text:"Re-themed"
                Style.Resources {
                    SolidColorBrush {ThemeBorderMidBrush:"Red"}
                    SolidColorBrush {ThemeControlHighBrush:"DarkRed"}
                }
            }
        }
        StackPanel{
            Orientation:"Vertical" Spacing:"8" Width:"150"
            Button {BorderThickness:"0" Text:"No Border"}
            Button {BorderBrush:"@ThemeAccentBrush" Text:"Border Color"}
            Button {BorderBrush:"@ThemeAccentBrush" BorderThickness:"4" Text:"Thick Border"}
            Button {BorderBrush:"@ThemeAccentBrush" BorderThickness:"4" IsEnabled:"False" Text:"Disabled"}
        }
    }   
}

And QML binding syntax:

SliderBar { Id=“sld” Min=0 Max=100}
TextBlock { Text: sld.Value }

The grammar of QML is well refined, just liking poem. QML has several advantages:

  1. Syntax like JSON
  2. Concise binding syntax
  3. Concise property syntax
  4. Signal and slot
  5. ...

The first 3 items can be adopted.
By the way, the file extension may be ".csml", It means "csharp markup language".
:)

@gulshan
Copy link

gulshan commented Apr 7, 2020

I think the specialty of UI frameworks like SwiftUI and Jetpack Compose is putting logical operations like if conditions and loops while defining UI code. Swift and Kotlin has some language features, that makes this possible. This will be hard to do in C#.

@VincentH-Net
Copy link

@gulshan said:

I think the specialty of UI frameworks like SwiftUI and Jetpack Compose is putting logical operations like if conditions and loops while defining UI code. Swift and Kotlin has some language features, that makes this possible. This will be hard to do in C#.

Actually, it's not that hard. #CSharpForMarkup is now built-in in Xamarin Forms as the C# Markup feature, and makes it easy to combine declarative and procedural buildup of markup.
It is currently in the 4.6 prerelease NuGet. The documentation will go live when 4.6 goes stable; for now see the merged Xamarin Forms PR for full documentation.

@surfsky In contrast to Razor-like approach C# Markup does not add / mix new language elements to C#, and avoids strings for data binding or property values, choosing typesafe, intellisense-supported C# features instead. However the markup structure reads similar to your example.

@gulshan
Copy link

gulshan commented Apr 15, 2020

@VincentH-Net I followed the PR and I really admire what you did. But what I tried say is, Jetpack compose supports code like this-

Column {
    people?.forEach { person ->
        Padding(16.dp) {
            Text(text = "${person.name} (${person.craft})")
        }
    }
}

We cannot put a loop or a conditional statement within a collection initializer in C#.

@VincentH-Net
Copy link

VincentH-Net commented Apr 16, 2020

@gulshan said

I followed the PR and I really admire what you did. ...
We cannot put a loop or a conditional statement within a collection initializer in C#

Thanks for the compliment!

Actually you can do this because #CSharpForMarkup has built-in helpers to mix-in logic with declarative markup: .Invoke() and .Assign().
E.g. above could be:

new StackLayout { Spacing = 16 }
    .Invoke(s => people?.ForEach(person => s.Children.Add(
        new Label { Text = $"{person.Name} ({person.Craft})" }
    )))

Or, if you want the label text to update to changes in person, you can add a calculated property and bind it like this:

class Person : BaseViewModel
{
    public string Name { get; set; }
    public string Craft { get; set; }

    public string NameAndCraft => $"{Name} ({Craft})";
}

new StackLayout { Spacing = 16 }
    .Invoke(s => people?.ForEach(person => s.Children.Add(
        new Label { } .Bind (nameof(Person.NameAndCraft))
    )))

Or, you could factor out the logic to a method that either returns a new StackLayout or takes the StackLayout.Children as parameter.

Or, if you want to support hot reload optimally, you could .Assign (out peopleStack) and at the end of the Build() method call a void BuildPeopleStack() method that sets peopleStack.Children

Note that in Forms you would actually use a BindableLayout or ListView or Collectionview and bind to the collection, so you would not need the foreach logic anyway - but that would defeat the purpose of this discussion.

So there are quite a few options to do this, both inline and in separate methods. All because the versatility of C#. No magic, new syntax or strings needed :-)

@gulshan
Copy link

gulshan commented Apr 16, 2020

@VincentH-Net Actually SwiftUI and Jetpack Compose both use a little bit of code generation along with built-in language syntax, specially for "Container" view (with children views), like this-

freeze_header

I don't know if this is possible in C#. I think it will be something really nice to have in C#.

@luismts
Copy link

luismts commented Apr 23, 2020

I think @VincentH-Net the challenge now is getting C # HotReload into VS. If this is achieved, the number of people using C # projects will be massive.

LiveSharp is great, and it's not expensive. But many do not know it, and it is a disadvantage. The simple fact of knowing that you have to install a third-party tool, and more being paid, leaves this option for a specific audience.

@weitzhandler
Copy link
Contributor

@luismts I shall say hot reload + hot restart.

@JaggerJo
Copy link

JaggerJo commented Apr 23, 2020

With a language that's more suitable for DSLs the UI declaration can be just code.

We don't need yet another Razor/xaml thing IMHO..

The code below is a sample of (https://github.com/AvaloniaCommunity/Avalonia.FuncUI) with F#. Might be interesting... here are templates if you want to give it a spin.

module Counter =

    type CounterState = {
        count : int
    }

    let init = {
        count = 0
    }

    type Msg =
    | Increment
    | Decrement

    let update (msg: Msg) (state: CounterState) : CounterState =
        match msg with
        | Increment -> { state with count =  state.count + 1 }
        | Decrement -> { state with count =  state.count - 1 }
    
    let view (state: CounterState) (dispatch): IView =
        DockPanel.create [
            DockPanel.children [
                Button.create [
                    Button.onClick (fun _ -> dispatch Increment)
                    Button.content "click to increment"
                ]
                Button.create [
                    Button.onClick (fun _ -> dispatch Decrement)
                    Button.content "click to decrement" 
                ]
                TextBlock.create [
                    TextBlock.dock Dock.Top
                    TextBlock.text (sprintf "the count is %i" state.count)
                ]
            ]
        ]    

NewApp_screenshot

@asklar
Copy link
Member

asklar commented Jun 13, 2020

Shameless plug, check out a reactive extension to C#/XAML that I wrote for last year's hackathon, called CSX. It lets you have a syntax like JSX suck as:

<StackPanel
    Id="taskList"
    Grid.Row="1"
    Grid.Column="0"
    Grid.ColumnSpan="2">
    {
        return person.Tasks.Select(todo => CreateToDoItem(todo));
    }
</StackPanel>
<Grid.PointerReleased Handler={
        completionRateTextBlock.Opacity = 1.0;
        taskList.Visibility = taskList.Visibility == Visibility.Collapsed ? 
                              Visibility.Visible : Visibility.Collapsed;
    }/>

https://github.com/asklar/CSX

@mdtauk
Copy link
Contributor Author

mdtauk commented Jun 13, 2020

Xamarin is working on what it calls C# Markup

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/csharp-markup

Example

Grid grid = new Grid();

Label label = new Label { Text = "Code: " };
grid.Children.Add(label, 0, 1);

Entry entry = new Entry
{
    Placeholder = "Enter number",
    Keyboard = Keyboard.Numeric,
    BackgroundColor = Color.AliceBlue,
    TextColor = Color.Black,
    FontSize = 15,
    HeightRequest = 44,
    Margin = fieldMargin
};
grid.Children.Add(entry, 0, 2);
Grid.SetColumnSpan(entry, 2);
entry.SetBinding(Entry.TextProperty, new Binding("RegistrationCode"));

Content = grid;

@VincentH-Net
Copy link

See this spec for the next version of C# Markup in .NET MAUI (top: MVU, bottom: MVVM):
image

@Odonno
Copy link

Odonno commented Jun 15, 2020

@VincentH-Net That looks really interesting.

@sonnemaf
Copy link
Contributor

I have created an proof of concept for a MVU pattern in UWP. Maybe this can extend this discussion.

using MvuTest.Controls;
using System;
using Windows.UI;
using Windows.UI.Popups;
using Windows.UI.Xaml;

namespace MvuTest {

    public class MainPage : MvuPage {

        private TextBlock2 _tb;

        private int _count;

        protected override IUIElement2 Build() =>
            this.StackPanel(
                this.ToggleButton("Toggle it")
                    .Width(200)
                    .FontSize(30),
                this.Button("Increment", (sender, e) => {
                    _tb.Text($"Count {++_count}");
                }).HorizontalAlignment(HorizontalAlignment.Center),
                (_tb = this.TextBlock("Count 0"))
                    .FontSize(20)
                    .Foreground(Colors.Red),
                this.TextBox("Fons Sonnemans")
                    .Header("Name")
            ).Spacing(12)
             .HorizontalAlignment(HorizontalAlignment.Center)
             .VerticalAlignment(VerticalAlignment.Center);
    }

}

@mdtauk
Copy link
Contributor Author

mdtauk commented Jun 10, 2021

What are the chances of getting C# Markup as a first class option for WinUI development?

Looking at the latest Google IO and WWDC events, we now see a trend which follows on from Flutter and React Native for Declarative UI

Swift and SwiftUI for macOS and iOS

Kotlin and Jetpack Compose for Android

Will a decision be made for WinUI to prefer C# and C# Markup - so push resources to it, feature it over Xaml in sample apps, templates, conference demos etc.

This also brings up some issues. WinUI and Reunion supports C++ and various other language abstractions - so Xaml will need to remain for those other languages right?

@sonnemaf
Copy link
Contributor

I have the feeling that this is not high on the priority list. I don't think that this is really bad. I love XAML. It is great, consistent and not very difficult. It is verbose though. I would love to have a C# markup solution. But I don't need it. It would be a bonus. I think that other WinUI features like input validation are more essential for its success.

@mdtauk
Copy link
Contributor Author

mdtauk commented Jun 11, 2021

I have the feeling that this is not high on the priority list. I don't think that this is really bad. I love XAML. It is great, consistent and not very difficult. It is verbose though. I would love to have a C# markup solution. But I don't need it. It would be a bonus. I think that other WinUI features like input validation are more essential for its success.

Sure it's not a priority in terms of functionality, but Microsoft is missing a shift in developers expectations, as every other platform and framework is moving this way.

Meeting developers where they are this is Microsoft's current mantra

@Happypig375
Copy link

As I said, just use C#. C# provides a concise way to specify views already.

@RichiCoder1
Copy link

As I said, just use C#. C# provides a concise way to specify views already.

Compared to some of the tools mentioned above, it's not quite nearly as concise. Various libs and tools have made it better but not nearly as pleasant. This discussion item outlines it well: dotnet/maui#119 (comment)

@VincentH-Net
Copy link

VincentH-Net commented Jun 11, 2021

@mdtauk I have been championing C# Markup for all .NET UI frameworks for a couple of years now, and built a Gen 1 for Xamarin Forms (in XCT now). I pushed for proper C# hot reload which is now coming. I also have a nearly finished next-gen C# Markup version for WinUI 3 and UNO on the shelf. A small snippet (source):
image

However, to deliver C# Markup in a way so it can compete with Flutter and SwiftUI, also some tooling is needed: proposal

This requires assigning / hiring at least one high level engineer to implement and support this - for one or more .NET UI frameworks.

The past 6 months I am just waiting for any of the UNO / WinUI / MAUI teams - or maybe a team that targets multiple .NET UI frameworks, like the XAML tooling team - to wake up to the outside world and come to the realization that using a single language for declarative markup and logic is not the future but the present - and has been for a while now.

All arguments were already clearly discussed with involved teams (most with MAUI and UNO, WinUI 3 team not so much yet - they reacted a bit confused when I mentioned C# markup in their community calls but they indicated they had too much work and I could add it myself after they go open source).

So, the waiting is for the moment when MS / UNO think this is worth at least a single engineer's time (note that MAUI MVU is also just a single person, who has other tasks as well). If they want to hire me I might even say yes ;-)

It might help if many devs make their wishes known to those teams - Twitter linked to GitHub issues seem to work well in that regard (that is how I got C# Markup into Forms)

@mdtauk
Copy link
Contributor Author

mdtauk commented Jun 11, 2021

@VincentH-Net I agree completely. It needs someone within Microsoft to decide it needs to be built into the tooling, and given priority.

People adopting MAUI will be a big push, as I suspect that team will extol the virtues of a move away from XAML files.

But MAUI is C#, and whilst C# Markup makes total sense there, it doesn't cover C++ development.

MAUI will also be a subset of WinUI's feature set, and so will be limiting in that way.

The removal of the XAML designer is another thing to hamper Xaml dev.

@github-actions
Copy link

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 5 days.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale Aug 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Controls Triage
Discussion / Question
Development

No branches or pull requests