microsoft / xaml-standard

XAML Standard : a set of principles that drive XAML dialect alignment
Other
803 stars 50 forks source link

Discussion: XAML is more than XML. Code-behind needs consideration too #193

Open dotMorten opened 7 years ago

dotMorten commented 7 years ago

It's pretty clear that the XAML Standard effort is an XML spec only. It tries to avoid considering the code-behind aspect of things completely. Now I can understand wanting to limit yourself to this, however I think that's failing to understand that XAML as an XML spec alone isn't enough and is only half the battle. We need well-known APIs/patterns in code-behind too.

Now at this point the spec doesn't consider what language you're coding against - XAML could be used for any UI markup on any platform/language, so defining a specific set of standards around code-behind is tricky. However I don't think anyone is asking for such generic XAML standard - pretty much all of us are using .NET in our code-behind, and it would be nice with a .NET-specific subset in the XAML standard that specifies how you write code against the UI layer.

If you're coding a purist MVVM app and write absolutely no code-behind, sure this is a non-issue. However most of the code I've seen developers write over the years, often tend to not be MVVM, but use lots of code-behind, or at the very least write UI-specific code-behind like event handlers, flip visibility etc (the latter which is OK in an MVVM app, as it's UI specific only code).

The XAML and the code-behind is very tightly coupled, and I should expect a common set of PMEs. When we want to share our knowledge of XAML snippets, we expect that for instance click handlers maps to code-behind the same way in all platforms. That the signature of the handler is the same, the way I flip visibility in code-behind is the same, the way I add an extra control or update a text property in code-behind is the same, the way I assign the DataContext to a view, or the way I handle routed events to prevent bubbling, or use AddHandler to ignore event-bubbling cancellation. Dependency Properties and Attached properties are also so key to XAML, but these are both things defined in code. All the APIs that I daily code against that are UI specific should and must have a similar set of PMEs, or we're back to the issue of switching between UWP and Xamarin.Forms being a horrible painful transition. If I learned how to write UWP UI and code against it, those experiences should and must transfer to Xamarin.Forms; - not just at the XAML level, but also the code I write against that UI.

So yes I understand this might not be in the original spirit of the XAML standard, but I think it's a very important issue to address - even if that means being an extension to the XAML standard that just .NET APIs should/must follow. Because lets face it... almost all of the XAML developers (all of them?) are using .NET.

This issue is somewhat related to #58 but is a little more broad discussion.

tomzorz commented 7 years ago

I'm completely aligned with you on this. The early transition might be a bit painful, but we must think long-term, and not limit ourselves to a quick but really incomplete solution to our issues.

petroemil commented 7 years ago

If you're coding a purist MVVM app and write absolutely no code-behind, sure this is a non-issue.

This is not necessarily true. You don't directly write code-behind, but you might want to build UserControls or CustomControls or maybe implement Behaviours or AttachedProperties... Also XAML Styles are just a collection of Property setters, so knowing what kind of properties are available on the different controls would be nice too.

Mike-E-angelo commented 7 years ago

Yeah this is running up against some philosophical approaches here, namely to code-behind or not to code-behind. I have been on many projects where code behinds are the satan, and for those that have used code-behinds, they gave every reason to reinforce that fact.

That's not to say that it's not wrong, but it certainly is not the only (or even preferred) method of "coding" in Xaml.

Just keep in mind and consider that every line of .NET code that you write in a code behind is something that is taken away from the reach of the visual designer, which ultimately leads to higher TCO of the project under development. Resources that are required to develop/maintain code-behinds (ala CODE) are more expensive (per hour rate) than those required to develop/maintain data in a designer-friendly format (ala XML/Xaml/JSON/etc). As such, solutions that are more designer-friendly tend to be cheaper to develop and maintain throughout its life cycle.

This is an ideal, of course. Even in a best case scenario you are going to have to dive into code behinds from time to time (in my case it has been when a seriously ugly hack is required), so it would be nice to perhaps have this fleshed out in the case that happens.

dotMorten commented 7 years ago

@Mike-EEE This isn't yet another Codebehind-vs-not-codebehind religious discussion. Fact is a lot of people use code-behind and consideration for them them shouldn't be left behind. Let's stay on the subject instead.

@petroemil I'm completely with you. I do A LOT of custom control development. However going to the level of being able to reuse all your custom controls code might take it too far, and limit the standard from expanding enough, when having to consider least common denominators, and also being able to fully take advantage of the underlying platform.

mdtauk commented 7 years ago

There needs to be support for:

XAML Views No codebehind, used to describe how a UI looks, with another way to define how the UI works. This would need to work with a framework to tie code to UI like MVVM, Xamarin Forms, etc;

XAML Code For controls, both custom and user - which is self contained and can be delivered as a control binary. So these controls can exist without a framework like MVVM, and if they can be compiled maybe they can be language agnostic, so C++, C#, Java, Go, Swift - whatever language you use, it can still be consumed in XAML compatible projects.

petroemil commented 7 years ago

This whole XAML standard feels a little bit weird for me, because unlike with HTML5 and JavaScript, XAML and its code behind (the actual implementation of the controls, attached properties, behaviours, etc.) strictly belongs together. XAML is just a more comfortable, declarative language to compose .NET Objects, but not something that you can consider on its own.

Or we can go down on a similar route as HTML5 and JS where we have a pre-defined set of controls that everyone can use and then its up to the runtime to provide the specific implementation behind that contract. But I think it will only work with "Hello World" apps, and we wouldn't be able to build cross platform custom controls, behaviours, etc. Which would kinda defeat the purpose, I think.

Maybe its the wrong place and time to ask (I'm pretty sure there are serious discussions around this topic), but why XAML Standard is not an actual cross-platform UI framework for .NET Core / Mono? And the necessary low-level drawing libraries would be abstracted away to map them to the platform specific graphics APIs, instead of abstracting away such high level concepts as XAML Controls and then mapping them to platform specific controls. There are truly cross-platform UI frameworks like Unity UI, they are just pretty dumb because they are designed to build simple UIs for games, and not apps.

Mike-E-angelo commented 7 years ago

Ahhh I am certainly trying to stay on topic, Professor @dotMorten. Let's see if I can do better.

For instance, the statement:

The XAML and the code-behind is very tightly coupled,

This is not the case -- not by default, at least. You can choose to make it very tightly-coupled (as a great many have), and it is (currently) a more expensive solution to do it this way. I am in agreement that it would be valuable to have further support around this so that it is not so expensive to utilize this feature, for sure.

So I guess my on-topic contribution to this would be: let's indeed consider the code-behind aspect of Xaml development an official component of Xaml development, and in doing so, let's also look into the expensive aspects of this and see if we can make them less expensive (and cooler/more valuable) as well. πŸ‘

dotMorten commented 7 years ago

@Mike-EEE I'm sorry but you completely misunderstand this. You were talking about philosophical approaches and whether we should separate the developers code from the designer (it sounds pretty, but in practice almost no one splits the work up this way). What you were talking about is a coding pattern decision and why you ought to separate code and design and that was completely unrelated - I'm not trying to say you shouldn't use that pattern, just that with the disconnect, the true problem the XAML standard tries to solve is only half solved.

Here's why they are very tightly coupled:

<Grid x:Name="myGrid">
    <TextBlock x:Name="tb" Text="Tap me"  Visibility="Visible" Tapped="Text_Tapped" />
</Grid

Is completely equivalent to

Grid myGrid = new Grid();
TextBlock tb = new TextBlock() { Text = "Tap me", Visibility = Visibility.Visible };
tb.Tapped += Text_Tapped;
myGrid.Children.Add(tb);
// ...
public void Text_Tapped(object sender, RoutedEventArgs e)
{
   (sender as TextBlock).Visibility = Visibility.Collapsed;
    e.Handled = true; // Prevent parent UI elements from getting the Tapped event
}

Every piece of XAML can be translated to a predictable set of C# code, and vice versa. No guessing required.

If I set visibility in XAML and add a click handler there, I also expect to be able to set the click handler to the same property, and flip visibility in code-behind essentially the same.

Now whether this is pretty code or not is completely besides the point. Not everyone subscribes to the MVVM idea - especially not if performance or quick prototyping matters. No this issue is about predictability in the object model when switching between markup and code. The event handler above is a great example of where Xamarin.Forms would be completely different, but with the standard the XAML piece wouldn't be. Failing to define the most common code patterns in the standard is IMHO failing to create a completely useable XAML standard. I get XAML strictly speaking isn't C# code. But the problem that XAML Standard is first and foremost trying to solve, is only half-solved without considering the code that inevitably goes along with it. So what I'm saying is the XAML standard needs to expand its scope.

Mike-E-angelo commented 7 years ago

I appreciate your efforts in correcting my thinking here to get me on your page, @dotMorten. You were mostly successful. I was specifically talking about the x:Class="" directive which produces the link to the file that provides the code-behind component. If I am not mistaken, this directive is required and will not successfully produce any object in memory as outlined above. To be more specific, the Tapped event that is defined above should throw an exception as there is no x:Class that the markup has been bound to. Please kindly let me know if I have this wrong.

Conversely, the Xaml that you have written above without the event handler, or as such:

<Grid x:Name="myGrid" xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" xmlns:local="clr-namespace:Interactivity">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Tapped" >
            <i:InvokeCommandAction Command="{x:Static local:MySuperAwesomeCommand}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
    <TextBlock x:Name="tb" Text="Tap me"  Visibility="Visible" />
</Grid>

This is also perfectly valid Xaml and does not require a code-behind. Or rather, the code-behind is not a dependency/requirement of Xaml, and the Xaml does not know about the code-behind. To me, that is not "tightly-coupled."

FWIW, I think it's better to state that code-behinds are tightly-coupled to Xaml, not the other way around. Anything that you can do in a code-behind can be done in declarative markup in one way or another as demonstrated above. Therefore, Xaml is not tightly-coupled to code-behinds.

(Please also note that in my assertions and thinking here that I am thinking of WPF and Silverlight Xaml models. My statements above are indeed false in UWP/XF models, which may also be adding to the confusion here.)

EDIT: Thinking about this more, my thoughts were incorrect on this as well. One of the challenges here is that the x:Class is actually an attached property, so nothing that we are discussing at this level is technically tightly-coupled, but rather, loosely-coupled. It is probably better to think in the context of code-behinds being enabled or disabled. If enabled, then yes elements from the xaml-generated elements are aware of code-behind elements. This indeed makes them tightly-coupled.

One last note:

it sounds pretty, but in practice almost no one splits the work up this way

I would refrain from absolute statements such as these. Almost no one you know splits up the work this way, inasmuch as almost no one I know does the vice versa. :)

All that said, I am in agreement and on your page with the rest of your statements. πŸ‘

dotMorten commented 7 years ago

[...] the code-behind is not a dependency/requirement of Xaml, and the Xaml does not know about the code-behind

Not true in the XAML/codebehind case. The InitializeComponents() call in code-behind is in a way what loads the XAML. Also note the code behind is a "partial" class, because the compiler generates more code from the XAML file. Also look at the *.g.cs files generated in the /obj/ folder to see what I mean. Which answers the second thing:

To be more specific, the Tapped event that is defined above should throw an exception as there is no x:Class that the markup has been bound to. Please kindly let me know if I have this wrong.

Without the x:Class declaration the compiler wouldn't be generating partial code that's linked to the code, and the class wouldn't be able to load the XAML (granted you can in the old WPF/SL days load XAML from strings which doesn't have x:Class but we don't do that anymore, but yes that would have thrown, but SL/WPF isn't a consideration in this standard).

One of the challenges here is that the x:Class is actually an attached property

No that's just old-school XML referring to the namespace that 'Class' is defined in. You won't find an attached property named "Class" anywhere in the object model.

Mike-E-angelo commented 7 years ago

but yes that would have thrown, but SL/WPF isn't a consideration in this standard

Indeed what I was thinking. I know you are not a fan of brain dumps, but when I see "discussion" I immediately think "CHANCE FOR IMPROVEMENT ALL THE THINGS" meaning pulling in WPF/Silverlight, etc. From the outset, my thoughts were/are geared as such.

Additionally, I currently have one-hand tied behind my back as my development environment is in the middle of a complete refresh, and I do not have a UWP-enabled IDE readily available to me to adequately test stuff out before throwing it out for you clean up. πŸ‘Ό I appreciate you taking the time to correct... even if it is at my expense. πŸ˜†

Going forward, I will be sure to be better environmentally and contextually prepared as to not only add more value to the conversation, but to save you a few (OK, A LOT OF!) keystrokes. ⌨️

Mike-E-angelo commented 7 years ago

For those living on my (dated?) wavelength, "Code Behind" (official spelling) is considered a "framework" now. Professor @dotMorten was spittin' the knowledge, but I was playing hooky. Check it out:

(Courtesy of a post from last month by @mbcrump and @crutkas)

crutkas commented 7 years ago

@Mike-EEE how else would you classify it in the context we had to? If you feel strongly, please file an issue over at https://github.com/Microsoft/WindowsTemplateStudio/ :)

crutkas commented 7 years ago

also @Mike-EEE, you're pushing the code of conduct limit (https://dotnetfoundation.org/code-of-conduct). Lets please keep it classy.

Mike-E-angelo commented 7 years ago

@crutkas Not exactly the reply I was aiming for, my good sir. I was not only complimenting your work but was/am also providing support for this thread to backup its intent. In particular, providing support for @dotMorten's earlier assessment:

Not everyone subscribes to the MVVM idea - especially not if performance or quick prototyping matters.

You have in fact provided credence to this view by labeling Code Behind as a "framework." I have never heard it called that and think that is a good way of putting it. Much like MVVM, it is a pattern/paradigm/way of thinking about concepts.

Also, I used the word "courtesy." Doesn't get much more classy than that. :)

dotMorten commented 7 years ago

I don't understand why you make the conclusion that "Framework" and "Code Behind" is the same thing. All they say is that the application is built with an MVVM framework. But that has nothing to do with code behind. It might negate the need for code-behind but it's still something entirely different. Again you are way off topic here ruining this discussion. WTF are we now discussing whether it's called framework and code behind, when I'm trying to start a discussion whether the UI specific code should be considered part of the spec in addition to the XAML? Now people have to read through all these long senseless discussions of me trying to keep this discussion on track, only to get bored before they get down to comments that might actually make sense. "Thank you" for that, and please stop the "Professor" BS too.

Mike-E-angelo commented 7 years ago

Wow, I am not sure what to say, so I'll keep it concise. Please know that I was complimenting your style of dissertation @dotMorten and giving credit to your published work, @crutkas. This was done while providing content that I felt contributed to the topic at hand. I apologize for any misunderstanding.

crutkas commented 7 years ago

@Mike-EEE it is the professor comments toward @dotMorten

Mike-E-angelo commented 7 years ago

Awww man, you guys. The context is: "the professor has arrived. Class in now is session." I was playing hooky, so I missed out on the truth at hand. The analogy here is very clear. But, I just as clearly misjudged my audience, so again that is on me.

nigel-sampson commented 7 years ago

To step away from the code behind debate, as someone who develops an MVVM framework which has tight coupling to the UI framework of the platforms in question I have a vested interest in seeing the UI layers being not just xaml compatible but source compatible. The less I have to do of the following the happier I'll be.

#if XAMARIN_FORMS
view.BindingContext = viewModel;
#else
view.DataContext = viewModel;
#endif
crutkas commented 7 years ago

@nigel-sampson i suggest making that its own issue to directly raise it

birbilis commented 7 years ago

@crutkas would probably call that "Code-behind logic" or something in the Template Studio to avoid confusion. After all rarely you see no Code-behind generated at all (e.g. in cases where XAML is loaded and parsed dynamically as a graphics or object graph serialization asset, say via omnixaml or system.xaml etc)

crutkas commented 7 years ago

@birbilis please put that feedback in the appropriate spot, https://github.com/Microsoft/WindowsTemplateStudio/ github. The XAML standard github is not the appropriate spot.

birbilis commented 7 years ago

Actually since the thread title speaks of code-behind, should first maybe have a common language on what exactly we call code-behind.

birbilis commented 7 years ago

Since @dotMorten seems to be posting and deleting replies, so that email delivery occurs only, I'll have to reply here. I know what codebehind is, but judging from template studio and MikeEEE's text in this thread, there seems to be some too relaxed usage of the term. Also, I'd probably treat differently tooling generated codebehind (that sometimes is regenerated and has do-not-edit note), from codebehind logic the user adds

nigel-sampson commented 7 years ago

Is is really just about code behind? The impression I got from @dotMorten is this is more about being "source compatible" and not just "markup compatible" (correct me if I'm wrong). Hesitant to raise yet another issue on this as between this issue and #58 I feel like the same thing is being attacked from a few different angles.

dotMorten commented 7 years ago

@nigel-sampson It's about solving the typical pieces of code-behind you would write in your page logic. It's about bringing consistency between the markup you use to set up the UI, and the code you write to interact with that UI. Now as stated before I don't think it's feasible to establish a full 100% compatible object-model, including templating and custom controls. The life-cycle and layout patterns are too different from platform to platform. But I would expect some of the basic concepts we use all the time like updating visibility, add/remove children, dependency properties, data context handling, routed events firing/bubbling to all follow the same patterns, since this is stuff developers very often write in the code-behind of pages and user controls.

[removed part for being off topic (admin crutkas)]

nigel-sampson commented 7 years ago

Fair enough, I guess there will always be some debate about where that line should be in regard to source compatibly, your list above does sound like a good starting point for that discussion though.,

birbilis commented 7 years ago

This is also related to the "Interface-based implementation" issue (#95). With interfaces used for PME (Property-Method-Event), implementing platforms could keep existing architecture and add interface implementations inside existing classes and/or via helper objects (helper objects can also help when working with precompiled older code, although nowadays it's more often to have source available)

birbilis commented 7 years ago

[off topic (admin crutkas)]

birbilis commented 7 years ago

Speaking of interfaces, maybe if XAML Standard is decided to stay at the xml vocabulary only, separate XAML Components and/or XAML Services Standard(s) could accompany it

mossyblog commented 7 years ago

How can XAML and python co-exist? .. moreover XAML and C#, Java, C++ etc...

Thats where this position falls down, and imho to layer in code-behind moves it away from a "standard" to a "specification".

This entire github repo so far has a huge identity crisis.

birbilis commented 7 years ago

The spec should have profiles/layers, one for the xml vocabulary, one for interfaces

SuperJMN commented 7 years ago

Hey people, this is what I understand as XAML Standard. Please, tell me your opinions. https://github.com/SuperJMN/OmniGUI

crutkas commented 7 years ago

@SuperJMN please don't spam, you posted same stuff in multiple issues.

SuperJMN commented 7 years ago

@crutkas Sorry, but since creating/commenting issues is not an adequate way to collaborate I decided to post in the 2 biggest discussion "threads" to get the enough visibility. Why? Because I think it is of interest for everyone here.

Anyways, I won't double-post more. Regards :)

mossyblog commented 7 years ago

@SuperJMN so ...let me get this right, you think this is the right time to conduct guerrilla marketing tactics... slaps forehead... we're just doomed to repeat the same mistakes.

SuperJMN commented 7 years ago

I wouldn't call it that way πŸ˜… But pardon me if I did wrong.

rodrigoelp commented 7 years ago

@mossyblog, you are awesome.

Most of the issues created are trying to specify 'how can the new standard be developed without having to learn something new'

XAML is not just xml and is not just for UI (as the initial comment on this thread specifies.

GeraudFabien commented 7 years ago

I didn't agree with the need of code behind more I can't see how you can do that :

asyncawaitmvvm commented 7 years ago

I'm confused, is OP asking for enhanced !CDATA support?

FYI2OP: Custom attached Blend behaviors are how you eliminate 99% of code-behind and scale your development like crazy. You can also generalize the ItemsSource pattern as a behavior base class and turn any mess into a clean MVVM-capable collection. I'm surprised nobody writes articles on this.

Mike-E-angelo commented 7 years ago

100% agree @asyncawaitmvvm and that is how I prefer to approach the problem as well, but not everyone sees it that way. Code behinds are useful for quick experimentation and other development purposes. Whether or not that has a place in a standard is the driving force behind this discussion.

birbilis commented 7 years ago

Object Model is not just for writing code by hand. Also 4G languages (e.g. visual ones) need some API in order to talk to an object. When you want to create dynamic UI or other visual UI editors (without spitting out intermediate XAML) for the user etc., you need to interact with the UI via code. Also to do things that might be more cumbersome to do declaratively, say when you want to make some game with UI elements used as game objects (assuming you have at last a fast renderer that doesn't choke with many "objects" in the "scene"). And I'm also thinking of Xaml 3D here for VR/AR etc. in the future.

stewienj commented 7 years ago

To me discussions like this take away from what should be the goal of XAML Standard. I imagine that I can use whatever UI Toolkit I want, and at a minimum it will be able to consume a XAML Standard .xaml file. So suppose there's some hot new WebGL based Toolkit that I use in my C# based WebAssembly app in the future. I can take my XAML layout files and just compile them in, however I will have to recode my code-behind stuff, because the WebGL widgets are a completely different set of controls to the WPF stuff I've been coding against. If you want to do some fancy pants coding-against the metal thing, well then you need to code directly against the UI Toolkit you are writing for, in my case I might need to write WebGL code. The audience here are advanced programmers, we know our stuff and can go deep into the low level framework stuff, but there's a whole lot of people out there who don't want to write custom controls, they just want to bind their data to what ever they've been given in the widget toolkit their boss purchased for the team.

dotMorten commented 7 years ago

@Stewienj I think you're over-interpreting. OpenGL isn't proposed to be part of the standard. What the ask is that XAML Elements that have a common markup also have a common object model to code against. Ie if I can set the Text probably like this in XAML:

<TextBlock x:Name="tb" Text="Hello" />

Then I can also write this in code-behind:

tb.Text = "Hello";

This becomes much more apparent with click handlers. You would expect that on all platforms it would probably be:

public void Button_Click(Sender object, RoutedEventArgs eventArgs)

Will that always be the code-behind signature?

Another example is in WPF/UWP you set visibility like this:

myElement.Visibility = Visibility.Collapsed;

in Xamarin.Forms you do it like this:

myElement.IsVisible = false;

It has been suggested that the XAML Standard is free to re-interpret Visibility into a Boolean in code-behind creating a huge disconnect between markup and code, making it unpredictable, and harder to reuse snippets. Sure you can argue that a purist MVVM app avoids this problem (since there wouldn't be any UI code), but most devs don't use MVVM (right or not), and a lot of those who do, does consider simple UI-specific code (which the above is) to be ok in code-behind.

mossyblog commented 7 years ago

Show me how i can write python+xaml, js+xaml, c#+xaml, java+xaml.

This is the point is it not? XAML is supposedly a standard but by the looks of this entire thread it not only lacks scope/governance but it doesn't really have the maturity/backing.