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

[Spec] CSharpForMarkup #8342

Merged
merged 69 commits into from Feb 27, 2020
Merged

[Spec] CSharpForMarkup #8342

merged 69 commits into from Feb 27, 2020

Conversation

VincentH-Net
Copy link
Contributor

@VincentH-Net VincentH-Net commented Oct 31, 2019

CSharpForMarkup

Fluent helpers and classes to make building Xamarin Forms UI in declarative style C# a joy.

Modern UI frameworks such as Flutter and SwiftUI offer declarative UI.
These helpers offer a similar approach for Xamarin Forms (the UI pattern remains MVVM though, this feature does not add MVU).

The goal is to make Xamarin Forms more attractive for additional developer audiences that don't have XAML skills / preference. Developers with XAML skills can also benefit; declarative C# can be very similar to XAML and can offer increased productivity (due to excellent IDE support for C# and no need for language bridging mechanisms).

This feature is based on CSharpForMarkup (226 stars atm).
This PR code is unit tested with 100% code coverage, and has been tested against this Production App by replacing CSharpForMarkup with it.

API

The API is an opt-in set of fluent helpers and classes that extend BindableObject, Element, Layout, Style and some specific view types. No existing Forms code is touched. There is no impact on existing apps code.

Developers opt in by calling Forms.SetFlags("Markup_Experimental") before calling Forms.Init, and adding these usings to a markup .cs file:

using Xamarin.Forms.Markup;
using Xamarin.Forms.Markup.LeftToRight; // Optional; 0 or 1 of .LeftToRight or .RightToLeft
using static Xamarin.Forms.Markup.GridRowsColumns; // Optional

The separate Markup namespace promotes a clean separation between UI markup and UI logic. It is recommended to split C# markup and UI logic into separate partial class files, e.g:

  • LoginPage.cs
  • LoginPage.logic.cs

Developers who do not include the above namespaces will have nothing of this code in their linked app or in their intellisense; zero impact.

The helpers offer a fluent API with Bind, Gesture, Effects, Invoke, Assign, Row, Column, FormattedText, Style, Font, inline converters, support for using enums for Grid rows + columns and more.
Simple to add to in app code; developers can also easily create their own markup DSL on top of this,
as in this example in David Ortinau's Xappy.

C# Examples

Just an Entry with Style, Row, Margins and Bind:

new Entry { Placeholder = "123456", Keyboard = Keyboard.Numeric } .Style (Styles.FieldEntry)
           .Row (Row.CodeEntry) .Margins (left: entryAlignLeftMarginSize)
           .Bind (nameof(vm.RegistrationCode))

A few more layout helpers ColumnSpan, Right, FillExpandHorizontal, CenterVertical, Bottom, Margin, Height, TextCenterHorizontal:

PageCSharpShort

Methods

Extension methods to set select view properties. The helpers are not meant to replace all property setters; they are added when they improve readability. They are meant to be used in combination with normal property setters. It is recommended to always use a helper when one exists for a property, but developers can choose a balance they prefer (e.g. to keep the markup more or less similar to XAML).

Binding, commands and converters

Use Bind as in the above C# examples.

Note that Bind knows the default bindable property for most built-in Forms view types; you can omit the target property in most cases. You can also register the default bindable property for additional controls:

DefaultBindableProperties.Register(
    HoverButton.CommandProperty, 
    RadialGauge.ValueProperty
);

You can bind to any bindable property like this:

new Label { Text = "No data available" }
           .Bind (Label.IsVisibleProperty, nameof(vm.IsEmpty))

Use BindCommand to bind to a view's default Command and CommandParameter properties in a single call:

new TextCell { Text = "Tap Me" }
              .BindCommand (nameof(vm.TapCommand))

By default the CommandParameter is bound to the binding context (e.g. the item in a list). You can specify the binding path and source for the Command and the CommandParameter bindings:

new TextCell { Text = "Tap Me" }
              .BindCommand (nameof(vm.TapCommand), vm, nameof(Item.Id)) // Here the binding context is an Item instance, so we don't need to specify a source for the "Id" CommandParameter binding

If you only need to bind to Command, you can pass null to BindCommand's parameterPath parameter, or simply use Bind (for most views that have a Command parameter it is the default bindable property; using Bind then is the most concise).

You can also register the default Command and CommandParameter properties for additional controls:

DefaultBindableProperties.RegisterForCommand(
    (CustomViewA.CommandProperty, CustomViewA.CommandParameterProperty),
    (CustomViewB.CommandProperty, CustomViewB.CommandParameterProperty)
);

Pass inline converter code with convert and convertBack parameters (type-safe):

new Label { Text = "Tree" }
           .Bind (Label.MarginProperty, nameof(TreeNode.TreeDepth), 
                  convert: (int depth) => new Thickness(depth * 20, 0, 0, 0))

Type-safe converter parameters are also supported:

new Label { }
           .Bind (nameof(viewModel.Text),
                  convert: (string text, int repeat) => string.Concat(Enumerable.Repeat(text, repeat)))

Re-use converter code and instances with FuncConverter:

treeMarginConverter = new FuncConverter<int, Thickness>(depth => new Thickness(depth * 20, 0, 0, 0));
//...
new Label { Text = "Tree" }
           .Bind (Label.MarginProperty, nameof(TreeNode.TreeDepth), converter: treeMarginConverter),

FuncConverter<TSource, TDest, TParam> also supports CultureInfo:

cultureAwareConverter = new FuncConverter<DateTimeOffset, string, int>(
    (date, daysToAdd, culture) => date.AddDays(daysToAdd).ToString(culture)
);

Use FormattedText together with binding to Spans:

new Label { } .FormattedText (
    new Span { Text = "Built with " },
    new Span { TextColor = Color.Blue, TextDecorations = TextDecorations.Underline }
              .BindTapGesture (nameof(vm.ContinueToCSharpForMarkupCommand))
              .Bind (nameof(vm.Title))
)

Gesture recognizers

To bind Command and (optionally) CommandParameter to GestureElement (e.g. Span) and View types using gesture recognizers, use BindClickGesture, BindSwipeGesture and BindTapGesture:

new Label { Text = "Tap Me" }
           .BindTapGesture (nameof(vm.TapCommand))

This creates a gesture recognizer of the specified type and adds it to the view.
The Bind*Gesture helpers offer the same parameters as BindCommand, however by default Bind*Gesture does not bind CommandParameter, while BindCommand does.

To initialize a gesture recognizer (e.g. parameters), use ClickGesture, PanGesture, PinchGesture, SwipeGesture and TapGesture:

new Label { Text = "Tap Me" }
           .TapGesture(g => g.Bind(nameof(vm.DoubleTapCommand)).NumberOfTapsRequired = 2)

Note that since a gesture recognizer is a BindableObject, you can use Bind and BindCommand when you initialize it (as shown above).
You can also initialize custom gesture recognizer types with Gesture<TGestureElement, TGestureRecognizer>

Layout

Use layout helpers for positioning views in layouts and content in views:

  • In a Grid: Row, Column, RowSpan, ColumnSpan
  • In a FlexLayout: AlignSelf, Basis, Grow, Menu, Order, Shrink
  • Specify LayoutOptions:
    • Left, CenterHorizontal, FillHorizontal, Right
    • LeftExpand, CenterExpandHorizontal, FillExpandHorizontal, RightExpand
    • Top, Bottom, CenterVertical, FillVertical
    • TopExpand, BottomExpand, CenterExpandVertical, FillExpandVertical
    • Center, Fill, CenterExpand, FillExpand
  • Margin, Margins
  • Height, Width, MinHeight, MinWidth, Size, MinSize
  • Padding, Paddings
  • In a Label:
    • TextLeft, TextCenterHorizontal, TextRight
    • TextTop, TextCenterVertical, TextBottom
    • TextCenter

LTR and RTL support

For markup that is designed to support either left-to-right or right-to-left flow direction the helpers listed above offer the most intuitive set of names: Left, Right, Top & Bottom.

To make the correct set of Left & Right helpers available - and in the process make explicit which flow direction the markup is designed for - include either:
using Xamarin.Forms.Markup.LeftToRight, or
using Xamarin.Forms.Markup.RightToLeft.

For markup that is designed to support both left-to-right and right-to-left flow direction, it is recommended not to include either one of above namespaces, and instead use the Start & End set of helpers from the Xamarin.Forms.Markup namespace - their names are flow direction agnostic by design, and fit this scenario best:

  • Specify LayoutOptions:
    • Start, End
    • StartExpand, EndExpand
  • In a Label:
    • TextStart, TextEnd

Layout line convention

The recommended convention is to put all helpers from above set for a view on a single line, in the order that they are listed above. This creates a layout line that visually zooms in on the view. content:

  1. Row & column that contain the view
  2. Alignment within row & column
  3. Margin around view
  4. View size
  5. Padding within view
  6. Content alignment within padding

Consistently applying this convention enables developers to quickly visually scan and zoom in on markup to build a mental map of where the view content is located.

Enums for Grid rows and columns

By adding using static Xamarin.Forms.Markup.GridRowsColumns; you can use enums for Grid rows and columns instead of numbers, so you don't have to renumber manually when you add or remove rows or columns. Readability and intent of the layout is also improved:

Enums For Grid Rows And Columns

You can also concisely define rows and columns without enums:

new Forms.Grid
{
    RowDefinitions = Rows.Define(Auto, Star, 20),
    ColumnDefinitions = Columns.Define(Auto, Star, 20, 40)
    ...
}

Fonts

  • In any Element that implements IFontElement (Button, DatePicker, Editor, Entry, Label, Picker, SearchBar, Span, TimePicker) : FontSize, Bold, Italic, Font

Effects

new Button { Text = "Tap Me" }
.Effects (new ButtonMixedCaps())

Logic integration

Use Invoke to execute code inline in your declarative markup:

new ListView { } .Invoke (l => l.ItemTapped += MyListView_ItemTapped)

Use Assign if you need to access a control from outside the UI markup (in UI logic):

new ListView { } .Assign (out MyListView),

Styles

Use Style to create type-safe, declarative coded styles:

using static CSharpForMarkupExample.Styles;
...
new Button { Text = "Tap Me" } .Style (FilledButton), // Use .Style for VisualElement types
...
new Span { Text = "delightful", Style = Quote }, // Use the implicit Style type converter for other Element types

Styles In C Sharp

Note that instead of using Style, you can simply create your own extension methods to set styling even more type-safe:

new Button { Text = "Tap Me" } .Filled ()
public static TButton Filled<TButton>(this TButton button) where TButton : Button
{
    button.Buttons(); // Equivalent to Style .BasedOn (Buttons)
    button.TextColor = Color.White;
    button.BackgroundColor = Color.Red;
    return button;
}

Platform Specifics

Use Invoke to apply platform specifics. To avoid ambiguity errors, don't include the Xamarin.Forms.PlatformConfiguration.*Specific namespaces directly; instead, create a namespace alias:

using PciOS = Xamarin.Forms.PlatformConfiguration.iOSSpecific;

and then you can use platform specifics like this:

new ListView { } .Invoke (l => PciOS.ListView.SetGroupHeaderStyle(l, PciOS.GroupHeaderStyle.Grouped))

If you use certain platform specifics often, you can create fluent helpers for them in your own extensions class, e.g. like this:

public static T iOSGroupHeaderStyle<T>(this T listView, PciOS.GroupHeaderStyle style) where T : Forms.ListView
{ PciOS.ListView.SetGroupHeaderStyle(listView, style); return listView; }

and then you can use them like this:

new ListView { } .iOSGroupHeaderStyle(PciOS.GroupHeaderStyle.Grouped)

Conventions

Recommended markup formatting conventions for every control:

  • Bound properties are last, one per line. The default bindable property, if any, should be the very last line.

  • The line before the bound properties is about layout, ordered inward: rows / columns, layout options, margin, size, padding, content alignment.

    Consistently applying these conventions allows to visually scan / zoom markup and build a mental map of the layout.

  • Before that are the other properties; any property that identifies the control's purpose should be on the very first line (e.g. Text or Placeholder)

Backward Compatibility

There are no breaking changes. All platforms are supported.

Area's where functionality still can be added:

  • Add Shell helpers

Difficulty : [low]

Because it is fairly complete and thoroughly battle-tested.

Platforms Affected

  • Core (all platforms)

Behavioral/Visual Changes

None

Testing Procedure

This PR includes comprehensive unit tests - 100% code coverage.

This PR code also has been tested against this Production App by replacing CSharpForMarkup with it.
If preferred, some example pages can be added to the PagesGallery project for testing.

Vincent Hoogendoorn added 6 commits Oct 31, 2019
…Markup/blob/061566282706de22d040e5b7b32bc3c2e3e323e3/src/XamarinFormsMarkupExtensions.cs

- Remove specific converters
- Fix .NETStandard 1 build errors by refactoring IConvertible to Enum generic constraints
- Add RegisterDefaultBindableProperties method
- Reformat source to comply with Forms contibuting guidelines
… impact on existing code and to support clear separation of UI markup from UI logic

- Split up source file for better maintainability
- Names of generic types and variables to reflect where clauses
- Namespaces remove unused & sort
- Add whitespace
- Remove unused file
Remove RowCol helpers because compiler cannot infer its generic type parameters. Use Row and Col methods instead
@dnfclas
Copy link

@dnfclas dnfclas commented Oct 31, 2019

CLA assistant check
All CLA requirements met.

@rogihee
Copy link
Contributor

@rogihee rogihee commented Nov 1, 2019

I'm getting a full-circle feeling from this, after starting my Xamarin journey with @migueldeicaza https://github.com/migueldeicaza/MonoTouch.Dialog in 2013 (look at the sample code in the README).

Shameless plug for an MVU prototype: anyone interested should checkout @Clancey https://github.com/Clancey/Comet

@samhouts samhouts self-requested a review Nov 1, 2019
@samhouts samhouts added this to In Review in v4.5.0 Nov 2, 2019
@VincentH-Net
Copy link
Contributor Author

@VincentH-Net VincentH-Net commented Nov 2, 2019

I just updated the spec doc to include all helpers and explain intended usage

@VincentH-Net
Copy link
Contributor Author

@VincentH-Net VincentH-Net commented Nov 15, 2019

Maintainability and Codegen

During yesterday's discussion of this PR in the XamarinFormTeam live stream some concerns were mentioned about maintainability (there was great positive feedback from the team and the community chat as well, thanks all!). For maintainability a possible alternative approach was proposed: automatically generate a full fluent API.

I would like to address these concerns by demonstrating:

  • How maintaining the current partial & manual Fluent approach requires very little effort
  • How using codegen to automatically create a full fluent UI API would not improve C# markup readability or conciseness - which is the whole point of this PR.

Light Maintenance

I have been maintaining CSharpForMarkup for over 2 years and it has been very little work. To illustrate, in 2019 only 6 small commits were done to the helpers (note that in this PR the single helpers file already has been split up in multiple files for optimal maintainability)

When new UI will be added to Forms - e.g. a new control or a feature like Shell, there is only a need to add helpers for those properties (or property combinations) that are overly verbose and most often used. A helper is essentialy just one assignment statement, or a combination of helpers:

public static TLabel TextTop<TLabel>(this TLabel label) where TLabel : Label 
{
    label.VerticalTextAlignment = TextAlignment.Start; 
    return label; 
}

public static TLabel TextCenter<TLabel>(this TLabel label) where TLabel : Label => label.TextCenterH().TextCenterV();

This allready small effort can be even further reduced: initially a minimal amount of helpers can be added for a new control/feature. After a period where the control is used in apps, app developers will have added common convenience methods (it is trivially easy as shown above) which can be simply contributed in a PR. It can be a process of small steps for gradual-but optimal- improvement, which would grow a standard body of helpers.

The vast majority of existing helpers are for base classes (Element, View, VisualElement, Layout) and for layout classes that provide attached properties (Grid, FlexLayout). Additions to Forms of this type are relatively rare and even then would only require a handful of very similar methods.

The PR only accesses public Forms properties and methods. These are highly unlikely to change but even if they were, e.g. a rename would automatically be done since the PR is in the Core project (which is a benefit as compared to putting it in a separate NuGet). So there is no risk of changes in Forms causing maintenane in this PR.

The implementation in this PR has been used during more than 2 years in production apps; it is battle tested for stability and usability. It is already documented. All this value can be included in Forms for free.

In summary, future maintainance for the current implementation is very light.

CodeGen API would have little value

While automatically generating a full fluent API would prevent the above (light) maintenance, it would not improve much for the developer. C# markup is improved by intelligently choosing shorter names for the most often used (combinations of) overly verbose property setters. Simply automatically converting the vanilla Forms UI API to equivalent fluent methods would:

  • improve little compared to vanilla Forms C# UI
  • pollute IntelliSense
  • add much more code to apps

The codegen Fluent api approach has already been tried e.g. here is the most starred (17 stars) fluent Xamarin UI API:
https://github.com/dariodotnet/XamFluentUI
Note that CSharpForMarkup currently has 178 stars:
https://github.com/VincentH-Net/CSharpForMarkup

To illustrate why, compare below C# markup fragment in 4 different API's:

// Vanilla Forms:
new Label { Text = "Hi", HorizontalTextAlignment = TextAlignment.Center, VerticalTextAlignment = TextAlignment.Center },

// Generated 1:
new Label("Hi", horizontalTextAlignment: TextAlignment.Center, verticalTextAlignment: TextAlignment.Center),

 // Generated fluent 2:
new Label("Hi") .HorizontalTextAlignment(TextAlignment.Center) .VerticalTextAlignment (TextAlignment.Center),

// CSharpForMarkup:
new Label { Text = "Hi" } .TextCenter (),

A fully fluent API is not a goal, it is only a means to be used selectively and intelligently where it improves on the readability and conciseness of vanilla Forms C# markup.

As can be seen in above examples, no real improvement is achieved when automatically generating an API. Of course you can manually add attributes for the codegen, but that would mean equivalent or more effort and more complexity.

In short, building a fluent UI API + generator would be a lot of extra effort for a lot less value.

Getting it shipped

If the concerns are adequately addressed, possibly add an experimental flag to communicate that syntax may still be finetuned for a time, and it can be shipped!

PS Follow up possibilities:

  • We could start to write all new C# UI documentation examples in this style (OK because the current PR is in the Core project, something that may not be acceptable if it would be a separate NuGet).
  • Devs may also like a VS template in this style.
  • I've been thinking about creating an autoformatting tool/plugins ; experience has tought that markup C# readability improves with some different formatting options than for logic C#, and also automate more conventions (see conventions in PR description)

Thank you all for reading all this; please like if you agree or comment if you have additional concerns or questions. I believe that doing this right is important for the future of Forms (attracting more devs). Let's make this happen!

@davidortinau @samhouts @StephaneDelcroix

@muhaym
Copy link

@muhaym muhaym commented Nov 16, 2019

@VincentH-Net I would love to see a performance comparison for pages created using XAML vs C#
Complex Page Rendering results with performance insights will help developers to choose the way to go.

For instance, I have a very very complex page that has lot's of sub controls, which based on dynamic condition should be loaded, right now since Conditional XAML is not available, we use Visibility to meet the needs, but as the page grown in size and complexity, the page loading is severely slow (takes 1-2 seconds for rendering the UI in good phones).

@KSemenenko
Copy link
Contributor

@KSemenenko KSemenenko commented Nov 16, 2019

I like this feature. Sometimes I need to make page layout from code, and now this is not very convenient.

@VincentH-Net
Copy link
Contributor Author

@VincentH-Net VincentH-Net commented Nov 16, 2019

@muhaym CSharpForMarkup is by definition faster than XAML, even when compared to XAML with precompiled XAML and compiled bindings. At it's core XAML is just an object serialization format, built on top of the UI API that you directly access from C# when you use CSharpForMarkup. You simply bypass the XAML layer, and the compiler optimizes your C# markup better than XAML.

Also when using CSharpForMarkup you don't need to use any XAML to C# language bridging mechanisms (e.g. styles, resource dictionaries, behaviours, triggers, markup extensions), some of which can also be slowdowns.

I have used CSharpForMarkup to build a production app with some quite complex pages. I never experienced the type of slowness you describe. Actually people watching my video walkthrough asked if I speeded it up (I didn't).

You can check for yourself; download my app and select "or start demo" - you can navigate the full app UI with demo data to check the speed.

You can check the screen below, I use the same approach there that you do (all controls on the page, set visibility on the top tab select). I never needed to create the controls dynamically; it was already fast enough.

image

@Depechie
Copy link
Contributor

@Depechie Depechie commented Nov 16, 2019

Just for reference, since xamarin forms does UWP. Not all code is faster!
https://twitter.com/harini_kannan/status/994259239802617856?s=21

@SuNNjek
Copy link
Contributor

@SuNNjek SuNNjek commented Nov 20, 2019

@Depechie Don't the view renderers instantiate its controls via code anyway? Xamarin doesn't use UWP Xaml, so this shouldn't matter

@Depechie
Copy link
Contributor

@Depechie Depechie commented Nov 20, 2019

@SuNNjek yeah, that was my point exactly. But the statement that coded UI is faster is floating around and if you should do 'native' UWP dev, that statement is not true. But indeed because of the Xamarin Forms framework we can't benefit from that speed gain.

@KSemenenko
Copy link
Contributor

@KSemenenko KSemenenko commented Nov 20, 2019

I also wanted to know, will it code support the Shell?

@VincentH-Net
Copy link
Contributor Author

@VincentH-Net VincentH-Net commented Nov 21, 2019

@KSemenenko Yes, I have Shell support planned, see the PR description:

Area's where functionality still can be added:

  • Add bindable property default for more/all built-in Xamarin Forms controls
  • Add Shell helpers
  • Add helpers for more/all platform specifics

I might even get it included before review of this PR starts (it has been 3 weeks now, no idea how long that takes though).

Do you have some example pain points of working with Shell in C#?
I can make sure to address them. Thanks!

@KSemenenko
Copy link
Contributor

@KSemenenko KSemenenko commented Nov 21, 2019

Today I tried to create a Shell from the code.
minimal example:

var shell = new Shell();
shell.Items.Add(new TabBar()
{
	Items = { new Tab
	{
		Items = { new ShellContent()
		{
			Content = new StatusBarGalleryPage()
		}}
	}}
});

Application.Current.MainPage = shell;

Xamarin.Forms.Core/Markup/Style.cs Outdated Show resolved Hide resolved
@samhouts
Copy link
Member

@samhouts samhouts commented Feb 27, 2020

Hmm, I don't have a stage or a live streaming event to do this on....but...here goes....

@samhouts samhouts merged commit 1cf98d9 into xamarin:master Feb 27, 2020
2 checks passed
v4.6.0 automation moved this from In Progress to Done Feb 27, 2020
@hypervtechnics
Copy link

@hypervtechnics hypervtechnics commented Feb 27, 2020

So happy to see this getting merged!

@samhouts samhouts added this to Done in vCurrent (4.8.0) Feb 27, 2020
@samhouts samhouts added this to the 4.6.0 milestone Feb 28, 2020
@hminaya
Copy link

@hminaya hminaya commented Feb 28, 2020

👏

@VincentH-Net
Copy link
Contributor Author

@VincentH-Net VincentH-Net commented Feb 28, 2020

Hmm, I don't have a stage or a live streaming event to do this on....but...here goes....

Thanks @samhouts, @davidortinau, @hartez and everyone who supported this! Very happy to see this become a part of Forms.

@chrisparkeronline
Copy link

@chrisparkeronline chrisparkeronline commented Feb 28, 2020

This is so awesome team!

@uxsoft
Copy link

@uxsoft uxsoft commented Apr 30, 2020

Awesome, so the next step is to be able to make components with a state like React and Live code reload with state preservation for the ultimate developer experience!

@acaliaro
Copy link

@acaliaro acaliaro commented Apr 30, 2020

Awesome, so the next step is to be able to make components with a state like React and Live code reload with state preservation for the ultimate developer experience!

Next Step is HotRestart for Xamarin.Forms Android projects

@VincentH-Net
Copy link
Contributor Author

@VincentH-Net VincentH-Net commented Apr 30, 2020

Awesome, so the next step is to be able to make components with a state like React and Live code reload with state preservation for the ultimate developer experience!

Next Step is HotRestart for Xamarin.Forms Android projects

Thanks! LiveSharp already does that, stateful hot reload of C# Markup (and XAML) for any pattern, MVVM etc. MVU is not needed for that. But if you like MVU as a pattern you can check out Comet.

@uxsoft
Copy link

@uxsoft uxsoft commented Apr 30, 2020

Yes, LiveSharp is exactly what I had in mind. I also monitor Fabulous because I tend to prefer F# whenever I can, but it would be cool to have something working great out of the box! I'll check out comet, it looks interesting!

@VincentH-Net
Copy link
Contributor Author

@VincentH-Net VincentH-Net commented Jul 16, 2020

The CSharpForMarkup Part 2 PR (#11428) is up! :-)

It adds support for:

  • MultiBinding
  • MultiConverter
  • BindableLayout
  • RelativeLayout
  • DynamicResourc

Plus some minor improvements.

If you would like to see additions or changes in C# Markup, or just have general feedback or questions, please add them in the comments on #11428.

Thanks!

@MelbourneDeveloper
Copy link

@MelbourneDeveloper MelbourneDeveloper commented Jul 16, 2020

@VincentH-Net is there any reason this couldn't be abstracted a little more so that it could partially be moved up to WinUI (UWP) as well?

@VincentH-Net
Copy link
Contributor Author

@VincentH-Net VincentH-Net commented Jul 17, 2020

@MelbourneDeveloper The C# Markup approach can be applied to any .NET programmable UI framework. Including UWP WinUI and Blazor. However the commonality would be syntax, because UI object hierarchies and the update patterns differ. So not a code abstraction but a pattern

VincentH-Net added a commit to VincentH-Net/XamarinCommunityToolkit that referenced this issue Nov 2, 2020
* - Add MarkupExtensions from https://github.com/VincentH-Net/CSharpForMarkup/blob/061566282706de22d040e5b7b32bc3c2e3e323e3/src/XamarinFormsMarkupExtensions.cs
- Remove specific converters
- Fix .NETStandard 1 build errors by refactoring IConvertible to Enum generic constraints
- Add RegisterDefaultBindableProperties method
- Reformat source to comply with Forms contibuting guidelines

* - Move markup extensions to Xamarin.Forms.Markup namespace to prevent impact on existing code and to support clear separation of UI markup from UI logic
- Split up source file for better maintainability

* Cleanup:
- Names of generic types and variables to reflect where clauses
- Namespaces remove unused & sort
- Add whitespace
- Remove unused file

* Fix for incorrect type name in exception message
Remove RowCol helpers because compiler cannot infer its generic type parameters. Use Row and Col methods instead

* Add targetNullValue and fallbackValue parameters to binding helpers.
Equivalent to https://github.com/VincentH-Net/CSharpForMarkup/tree/bd7f99957653f5e813ec805e3dad88aa487b9526

* rename binding helpers sourcePropertyName parameter to path

* Enable Style<T> on BindableObject instead of Element to resolve xamarin/Xamarin.Forms#8342 (comment)

* Fix for Grid properties Row, Col, RowSpan, ColumnSpan not set when default value is specified VincentH-Net/CSharpForMarkup#7

* Support DefaultBindableProperties for BindableObject (was limited to Element)

* .Font:
- Support any IFontElement (was limited to Button, Label, Entry and Picker)
- Fix for italic ignored when bold == true

* Fix for .FontSize, .Bold, .Italic return Label instead of type derived from Label

* Unit tests batch 1: for LabelExtensions, LayoutExtensions, ViewExtensions

* Add DefaultBindableProperties for more BindableObject types

* Remove .Menu() helper from ViewInFlexLayoutExtensions (bc no relation to FlexLayout)

* Fix for .Row and .Col without span specified still sets span

* Rename MarkupBaseTestFixture.TestPropertySet to TestPropertiesSet

* Add unit tests for ViewInFlexLayoutExtensions, ViewInGridExtensions and VisualElementExtensions

* Add default bindable property for all applicable bindable objects in core.

* Add unit tests for DefaultBindableProperties

* Support Bind, Assign and Invoke on BindableObject (was Element)
Add inline doc to clarify purpose of Bind overloads

* Add unit tests for BindableObjectExtensions

* Fix for attributes not set in .Font
Rename fontSize parameter to size
Enable .FontSize, .Bold and .Italic on IFontElement (was Label)

* Add unit tests for ElementExtensions

* Add unit tests for ElementExtensions

* Add assert of exception message content in GetDefaultBindablePropertyForUnsupportedType

* Add unit tests for EnumsForGridRowsAndColumns

* Add inline doc to clarify purpose of gesture recognizer binding overloads
Rename private constant bindingContextPropertyName to bindingContextPath for clarity

* Add unit tests for Style; cleanup namespaces in Style

* Simplify BindableObjectExtensions implementation (functionality unchanged)

* Add IGestureRecognizers to GestureElement and View, to avoid code duplication when accessing the existing GestureRecognizers property

* - Add specific helpers for more built-in gesture recognizers
- Add helpers to support initializing gesture recognizers
- Eliminate duplicate code for View and GestureElement by using new IGestureRecognizers
- Simplify implementation
- Rename ViewGesturesExtensions to ElementGesturesExtensions

* Extract BindingHelpers from BindableObjectExtensionsTests

* Add unit tests for ElementGesturesExtensions

* Add support for typed converter parameters
Add asserts for conversion values in unit tests

* Add unit tests for FuncConverter

* Add missing calls to Bind overloads in unit test for supporting derived types in BindableObject extensions fluent API

* Cleanup: remove unneeded Xamarin.Forms. prefix from static class references

* Add unit tests for PlatformSpecificsExtensions

* Reorder FuncConverter type params to optimize for most common usage and to remain backwards compatible with https://github.com/VincentH-Net/CSharpForMarkup

* Extend Bind*Gesture helpers to support all possible binding parameters

* Rename EnumsForGridRowsAndColumns to GridRowColEnums

* Add BindCommand helper to bind to default Command + CommandParameter properties
Add RegisterForCommand to register default Command + CommandParameter properties for custom bindable objects

* - Change Bind*Gesture helper parameters to match BindCommand parameters, to enable binding to Command + CommandParameter in a single compact call (removed parameters did not make sense for a command).
- Add inline doc to more ElementGesturesExtensions helpers where needed
- Improve ElementGesturesExtensions source formattting for consistency and readability

* Remove PlatformSpecificsExtensions
(only 2 iOS-only helpers; replace with guidance in PR description on how to use any platform specific with .Invoke)

* Fix inline doc spelling: it's -> its

* Rename TextLeft -> TextStart, TextRight -> TextEnd to support RTL

* Add Columns.Define(width, width ...) and Rows.Define(height, height ...) overloads for Grid

* Rename Grid rows & columns extensions class to GridRowsColumns

* Change gesture recognizer helpers implementation from reuse existing instance to always add new instance

* Change Bind*Gesture helpers default to not bind the commandparameter (is the more common scenario)

* Rename BoolNotConverter to NotConverter and make it a 2-way converter

* Add culture support to FuncConverter

* Rename helpers Left -> Start, Right -> End
Add opt-in LeftToRight and RightToLeft helpers

* Rename Col -> Column throughout

* Rename H -> Horizontal and V -> Vertical throughout

* Add Markup_Experimental flag for all API methods and update all unit tests to run with and without the flag

* Re-add "Markup_Experimental" flag

* Add default bindable properties / test exclusions for new BindableObject types in core

* Add constructorHint to FuncConverter and Style for more clear experimental flag message

* Add default bindable property for RadioButton - fixes test AllBindableElementsInCoreHaveDefaultBindablePropertyOrAreExcluded failure
jfversluis added a commit to xamarin/XamarinCommunityToolkit that referenced this issue Nov 17, 2020
* [Spec] CSharpForMarkup (#8342)

* - Add MarkupExtensions from https://github.com/VincentH-Net/CSharpForMarkup/blob/061566282706de22d040e5b7b32bc3c2e3e323e3/src/XamarinFormsMarkupExtensions.cs
- Remove specific converters
- Fix .NETStandard 1 build errors by refactoring IConvertible to Enum generic constraints
- Add RegisterDefaultBindableProperties method
- Reformat source to comply with Forms contibuting guidelines

* - Move markup extensions to Xamarin.Forms.Markup namespace to prevent impact on existing code and to support clear separation of UI markup from UI logic
- Split up source file for better maintainability

* Cleanup:
- Names of generic types and variables to reflect where clauses
- Namespaces remove unused & sort
- Add whitespace
- Remove unused file

* Fix for incorrect type name in exception message
Remove RowCol helpers because compiler cannot infer its generic type parameters. Use Row and Col methods instead

* Add targetNullValue and fallbackValue parameters to binding helpers.
Equivalent to https://github.com/VincentH-Net/CSharpForMarkup/tree/bd7f99957653f5e813ec805e3dad88aa487b9526

* rename binding helpers sourcePropertyName parameter to path

* Enable Style<T> on BindableObject instead of Element to resolve xamarin/Xamarin.Forms#8342 (comment)

* Fix for Grid properties Row, Col, RowSpan, ColumnSpan not set when default value is specified VincentH-Net/CSharpForMarkup#7

* Support DefaultBindableProperties for BindableObject (was limited to Element)

* .Font:
- Support any IFontElement (was limited to Button, Label, Entry and Picker)
- Fix for italic ignored when bold == true

* Fix for .FontSize, .Bold, .Italic return Label instead of type derived from Label

* Unit tests batch 1: for LabelExtensions, LayoutExtensions, ViewExtensions

* Add DefaultBindableProperties for more BindableObject types

* Remove .Menu() helper from ViewInFlexLayoutExtensions (bc no relation to FlexLayout)

* Fix for .Row and .Col without span specified still sets span

* Rename MarkupBaseTestFixture.TestPropertySet to TestPropertiesSet

* Add unit tests for ViewInFlexLayoutExtensions, ViewInGridExtensions and VisualElementExtensions

* Add default bindable property for all applicable bindable objects in core.

* Add unit tests for DefaultBindableProperties

* Support Bind, Assign and Invoke on BindableObject (was Element)
Add inline doc to clarify purpose of Bind overloads

* Add unit tests for BindableObjectExtensions

* Fix for attributes not set in .Font
Rename fontSize parameter to size
Enable .FontSize, .Bold and .Italic on IFontElement (was Label)

* Add unit tests for ElementExtensions

* Add unit tests for ElementExtensions

* Add assert of exception message content in GetDefaultBindablePropertyForUnsupportedType

* Add unit tests for EnumsForGridRowsAndColumns

* Add inline doc to clarify purpose of gesture recognizer binding overloads
Rename private constant bindingContextPropertyName to bindingContextPath for clarity

* Add unit tests for Style; cleanup namespaces in Style

* Simplify BindableObjectExtensions implementation (functionality unchanged)

* Add IGestureRecognizers to GestureElement and View, to avoid code duplication when accessing the existing GestureRecognizers property

* - Add specific helpers for more built-in gesture recognizers
- Add helpers to support initializing gesture recognizers
- Eliminate duplicate code for View and GestureElement by using new IGestureRecognizers
- Simplify implementation
- Rename ViewGesturesExtensions to ElementGesturesExtensions

* Extract BindingHelpers from BindableObjectExtensionsTests

* Add unit tests for ElementGesturesExtensions

* Add support for typed converter parameters
Add asserts for conversion values in unit tests

* Add unit tests for FuncConverter

* Add missing calls to Bind overloads in unit test for supporting derived types in BindableObject extensions fluent API

* Cleanup: remove unneeded Xamarin.Forms. prefix from static class references

* Add unit tests for PlatformSpecificsExtensions

* Reorder FuncConverter type params to optimize for most common usage and to remain backwards compatible with https://github.com/VincentH-Net/CSharpForMarkup

* Extend Bind*Gesture helpers to support all possible binding parameters

* Rename EnumsForGridRowsAndColumns to GridRowColEnums

* Add BindCommand helper to bind to default Command + CommandParameter properties
Add RegisterForCommand to register default Command + CommandParameter properties for custom bindable objects

* - Change Bind*Gesture helper parameters to match BindCommand parameters, to enable binding to Command + CommandParameter in a single compact call (removed parameters did not make sense for a command).
- Add inline doc to more ElementGesturesExtensions helpers where needed
- Improve ElementGesturesExtensions source formattting for consistency and readability

* Remove PlatformSpecificsExtensions
(only 2 iOS-only helpers; replace with guidance in PR description on how to use any platform specific with .Invoke)

* Fix inline doc spelling: it's -> its

* Rename TextLeft -> TextStart, TextRight -> TextEnd to support RTL

* Add Columns.Define(width, width ...) and Rows.Define(height, height ...) overloads for Grid

* Rename Grid rows & columns extensions class to GridRowsColumns

* Change gesture recognizer helpers implementation from reuse existing instance to always add new instance

* Change Bind*Gesture helpers default to not bind the commandparameter (is the more common scenario)

* Rename BoolNotConverter to NotConverter and make it a 2-way converter

* Add culture support to FuncConverter

* Rename helpers Left -> Start, Right -> End
Add opt-in LeftToRight and RightToLeft helpers

* Rename Col -> Column throughout

* Rename H -> Horizontal and V -> Vertical throughout

* Add Markup_Experimental flag for all API methods and update all unit tests to run with and without the flag

* Re-add "Markup_Experimental" flag

* Add default bindable properties / test exclusions for new BindableObject types in core

* Add constructorHint to FuncConverter and Style for more clear experimental flag message

* Add default bindable property for RadioButton - fixes test AllBindableElementsInCoreHaveDefaultBindablePropertyOrAreExcluded failure

* Cross-Platform OS Theme APIs (#9958)

* Implement OnAppTheme

* Implement AppThemeColor

* Added tests

* Finishing up

* Implement UWP

* Xcode 11 and additional test

* Update Forms.cs

* Update ViewRenderer.cs

* Update ViewRenderer.cs

* Remove IAppThemeProvider

* Implemented RequestedThemeChanged

* Update WindowsBasePlatformServices.cs

* Bindable props and Android invalidate

* Update DefaultBindableProperties.cs

* Updates at runtime

* Review feedback part 1

* Implement VisualElement.OnRequestedThemeChanged

* UWP Dispatcher

* Add experimental flag

* ControlGallery restructure

* Update ViewRenderer.cs

* Update WindowsBasePlatformServices.cs

* iOS pre-13 fix

* AppTheme fix NRE (#10327)

* Various fixes

* Back to basics

* [Enhancement] Shapes (#9218)

* Added Shapes to Core and Core Gallery samples
Implemented basic Shapes on iOS

* Added basic shapes Android implementation

* Fixed UWP namespace conflicts

* Fixed WPF namespace conflicts

* Implemented basic shapes on UWP

* Fixed UWP Ellipse and Rectangle size issue

* Fixed Tizen Build

* Changes to fix the build errors

* Exclude shapes renderers from Tizen compilation

* Implemented LineCap and LineJoin in Android and iOS

* Implemented LineCap and LineJoin on UWP

* Fixed build error

* Updated Polygon sample

* Fixed UWP Build error (namespace conflicts)

* Fixed namespaces collision build error

* Added "Shapes_Experimental" flag

* Update UWP ShapeRenderer size logic

* Updated iOS and Android ShapeRenderer size logic

* Fixed UWP Build error

* Added WPF implementation

* Fixed Tizen Build error

* Added Shapes macOS implementation

* Fixed broken unit tests

* Use the same Shapes classes between UWP and WPF backends

* Fixed flipper macOS shape issue

* Changed Shape class to be abstract

* Added Polygon and Polyline unit tests

* Added more Shapes Unit Tests

* Moved Shapes to Xamarin.Forms.Shapes in Android, iOS and macOS

* Moved Shapes to Xamarin.Forms.Shapes namespace in Windows (UWP and WPF)

fixes #2452 (partially)
fixes #9178

* [Enhancement] Shapes (Path) (#9264)

* Added Path definition in Core (Shapes)
Implemented Path in Android and iOS

* Fixed Android build errors

* Fixed UWP Build

* Fixed WPF Build

* Implemented PathRenderer on UWP

* Added unit tests

* Fixed namespaces conflicts in Platform projects

* Changes to fix the build errors

* Implemented Path Transformations in Android and iOS

* Fixed Build error in WPF and UWP

* Implemented Path Transformations in UWP

* Fixed iOS Build error

* Changes to fix the Build (Path namespace conflict)

* More changes to fix the build error

* Fixed Windows Build errors

* Fixed Path size issue on UWP

* Added Shapes_Experimental flag

* Updated path sample

* Updated Android ShapeRenderer size logic

* Added Shape Aspect sample in Core Gallery

* Added more Shapes samples

* Updated UWP PathRenderer size logic

* Updated droid and iOS pathRenderer size logic (same behavior in all the platforms)

* Updated UWP ShapeRenderer

* Implemented Path in WPF Backend

* Fixed build error

* Initial Clip implementation in WPF and UWP (work in progress)

* Added Path implementation on macOS

* Added Clip implementation in Android, iOS and macOS

* Fixed broken unit tests

* Notify the change of Geometry if any of the child properties changed

* Added new sample clipping different views

* Fixed flipped shape issue on macOS

* Added support to Clip using EllipseGeometry, LineGeometry and RectangleGeometry in UWP

* Changed Shape class to be abstract

* Moved Shapes to Xamarin.Forms.Shapes in Android, iOS and macOS

* Moved Shapes to Xamarin.Forms.Shapes namespace in Windows (UWP and WPF)

* Fixed wrong property in LineGeometry

* Fixed build error

* Added Clip Performance sample in Core Gallery

* Update Matrix.cs

* Update RectangleGeometry.cs

* Update Xamarin.Forms.Platform.macOS.csproj

* Some duplicate classes

* Update PointCollectionTests.cs

* Update ImageButtonRenderer.cs

* Update Xamarin.Forms.Platform.iOS.csproj

* Update Xamarin.Forms.Platform.iOS.csproj

* Fixed tabs error

Co-authored-by: Samantha Houts <samhouts@users.noreply.github.com>

fixes #2452 (partially)
fixes #9178

* Add fluent DynamicResource markup helpers

* Add support for all IPaddingElement Elements to Padding markup helpers (was only Layouts)

* Make family first parameter of Font markup helper (reduces the need to use named parameters across all FontElement extensions)

* Add Stars(double) markup helper for Grids

* Add RelativeLayout markup helpers

* wip Add RelativeLayoutTests

* Add RelativeLayout markup helpers done

* Add BindableLayout markup helpers

* wip Add MultiBind and MultiConverter support to markup helpers

* - Add multiconverter markup helpers
- Improve Bind markup helpers: add multibinding, make more strongly typed, remove converterParameter where unused
- wip Add unit tests for multiconverter and multibind

* wip Add unit tests for multibind

* Move MultiBind helpers + tests to separate files
wip Complete MultiBind unit tests

* wip Add unit tests for MultiBind markup helpers

* Add unit tests for MultiBind and MultiConvert markup helpers

* Add overloads for Bindable Layout markup helpers that take a Func<object> instead of a DataTemplate

* move C# Markup out of forms with internalsvisibleto, eliminate reflection

* Markup API: build against Forms 5 NuGet, remove experimental checks, change namespace to Xamarin.CommunityToolkit.Markup, add TODO comments for inaccessible IPaddingElement

* Build against Forms 5 NuGet, change namespace to Xamarin.CommunityToolkit.Markup.UnitTests, remove experimental flag testing. add TODO comments for inacccessible API's

* Add PR link to TODO comment

* Update to Forms NuGets that have public IPaddingElement
Get unit tests working and succeeding except for issue in Forms

* Bring unit tests to 100% code coverage
Cleanup mocks and remove all unused code from them
Remove all unnecessary namespace usings

* prefix Markup top-level folders with Xamarin.CommunityToolkit.

* add Xamarin.CommunityToolkit.Markup.sln, eliminate Markup subfolders, fix notimplemented exception in MockPlatformServices

* include stylecop.json in Markup project

* add comment with Forms NuGets download url to project files

* add prefix Xamarin.CommunityToolkit. to namespaces and assembly names where missing

* add package settings, license and icon to markup project

* add MarkupSample solution

* fix android build errro due to max path length (remove solution folder)
complete MarkupSample

* remove dependency on internal Forms PaddingElement and FontElement classes

* add temporary msbuild target for downloading NuGets from Forms PR

* add markup to ci

* fix markup project folder names in ci

* fix markup temporary NuGet download in ci

* fix markup unit test project for ci

* use NuGets from PR as merged into Forms 5.5.0 branch
fix tests that fail due to Forms PR 12689 not yet merged

* remove experimental wrapper from markup unit tests
align markup unit test project packagereferences to xct unit test project

* fix all code formatting warnings where applicable
suppress remaining code formatting warnings with justification where not applicable

* add warning codes from GlobalSuppressions.cs to NoWarn in project files

* fix Forms version warning
revert adding warning codes in project files

* ci run all tests in single task

* align markup csproj to XCT csproj for same type of debug info in release package

* update forms version in markup sample

* update to Forms 5.0.0.1709-pre4
remove custom Forms NuGet download targets
update unit tests for Forms fix fix xamarin/Xamarin.Forms#12689

* Markup package version  to 1.0.0-pre4
Markup sample to Markup 1.0.0-pre4 and Forms 5.0.0.1709-pre4

Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
Co-authored-by: Javier Suárez <javiersuarezruiz@hotmail.com>
Co-authored-by: Vincent Hoogendoorn <dev@vincenth.net>
Co-authored-by: Vincent Hoogendoorn <vincenth@workstreampeople.com>
jfversluis added a commit to xamarin/XamarinCommunityToolkit that referenced this issue Nov 18, 2020
* [Spec] CSharpForMarkup (#8342)

* - Add MarkupExtensions from https://github.com/VincentH-Net/CSharpForMarkup/blob/061566282706de22d040e5b7b32bc3c2e3e323e3/src/XamarinFormsMarkupExtensions.cs
- Remove specific converters
- Fix .NETStandard 1 build errors by refactoring IConvertible to Enum generic constraints
- Add RegisterDefaultBindableProperties method
- Reformat source to comply with Forms contibuting guidelines

* - Move markup extensions to Xamarin.Forms.Markup namespace to prevent impact on existing code and to support clear separation of UI markup from UI logic
- Split up source file for better maintainability

* Cleanup:
- Names of generic types and variables to reflect where clauses
- Namespaces remove unused & sort
- Add whitespace
- Remove unused file

* Fix for incorrect type name in exception message
Remove RowCol helpers because compiler cannot infer its generic type parameters. Use Row and Col methods instead

* Add targetNullValue and fallbackValue parameters to binding helpers.
Equivalent to https://github.com/VincentH-Net/CSharpForMarkup/tree/bd7f99957653f5e813ec805e3dad88aa487b9526

* rename binding helpers sourcePropertyName parameter to path

* Enable Style<T> on BindableObject instead of Element to resolve xamarin/Xamarin.Forms#8342 (comment)

* Fix for Grid properties Row, Col, RowSpan, ColumnSpan not set when default value is specified VincentH-Net/CSharpForMarkup#7

* Support DefaultBindableProperties for BindableObject (was limited to Element)

* .Font:
- Support any IFontElement (was limited to Button, Label, Entry and Picker)
- Fix for italic ignored when bold == true

* Fix for .FontSize, .Bold, .Italic return Label instead of type derived from Label

* Unit tests batch 1: for LabelExtensions, LayoutExtensions, ViewExtensions

* Add DefaultBindableProperties for more BindableObject types

* Remove .Menu() helper from ViewInFlexLayoutExtensions (bc no relation to FlexLayout)

* Fix for .Row and .Col without span specified still sets span

* Rename MarkupBaseTestFixture.TestPropertySet to TestPropertiesSet

* Add unit tests for ViewInFlexLayoutExtensions, ViewInGridExtensions and VisualElementExtensions

* Add default bindable property for all applicable bindable objects in core.

* Add unit tests for DefaultBindableProperties

* Support Bind, Assign and Invoke on BindableObject (was Element)
Add inline doc to clarify purpose of Bind overloads

* Add unit tests for BindableObjectExtensions

* Fix for attributes not set in .Font
Rename fontSize parameter to size
Enable .FontSize, .Bold and .Italic on IFontElement (was Label)

* Add unit tests for ElementExtensions

* Add unit tests for ElementExtensions

* Add assert of exception message content in GetDefaultBindablePropertyForUnsupportedType

* Add unit tests for EnumsForGridRowsAndColumns

* Add inline doc to clarify purpose of gesture recognizer binding overloads
Rename private constant bindingContextPropertyName to bindingContextPath for clarity

* Add unit tests for Style; cleanup namespaces in Style

* Simplify BindableObjectExtensions implementation (functionality unchanged)

* Add IGestureRecognizers to GestureElement and View, to avoid code duplication when accessing the existing GestureRecognizers property

* - Add specific helpers for more built-in gesture recognizers
- Add helpers to support initializing gesture recognizers
- Eliminate duplicate code for View and GestureElement by using new IGestureRecognizers
- Simplify implementation
- Rename ViewGesturesExtensions to ElementGesturesExtensions

* Extract BindingHelpers from BindableObjectExtensionsTests

* Add unit tests for ElementGesturesExtensions

* Add support for typed converter parameters
Add asserts for conversion values in unit tests

* Add unit tests for FuncConverter

* Add missing calls to Bind overloads in unit test for supporting derived types in BindableObject extensions fluent API

* Cleanup: remove unneeded Xamarin.Forms. prefix from static class references

* Add unit tests for PlatformSpecificsExtensions

* Reorder FuncConverter type params to optimize for most common usage and to remain backwards compatible with https://github.com/VincentH-Net/CSharpForMarkup

* Extend Bind*Gesture helpers to support all possible binding parameters

* Rename EnumsForGridRowsAndColumns to GridRowColEnums

* Add BindCommand helper to bind to default Command + CommandParameter properties
Add RegisterForCommand to register default Command + CommandParameter properties for custom bindable objects

* - Change Bind*Gesture helper parameters to match BindCommand parameters, to enable binding to Command + CommandParameter in a single compact call (removed parameters did not make sense for a command).
- Add inline doc to more ElementGesturesExtensions helpers where needed
- Improve ElementGesturesExtensions source formattting for consistency and readability

* Remove PlatformSpecificsExtensions
(only 2 iOS-only helpers; replace with guidance in PR description on how to use any platform specific with .Invoke)

* Fix inline doc spelling: it's -> its

* Rename TextLeft -> TextStart, TextRight -> TextEnd to support RTL

* Add Columns.Define(width, width ...) and Rows.Define(height, height ...) overloads for Grid

* Rename Grid rows & columns extensions class to GridRowsColumns

* Change gesture recognizer helpers implementation from reuse existing instance to always add new instance

* Change Bind*Gesture helpers default to not bind the commandparameter (is the more common scenario)

* Rename BoolNotConverter to NotConverter and make it a 2-way converter

* Add culture support to FuncConverter

* Rename helpers Left -> Start, Right -> End
Add opt-in LeftToRight and RightToLeft helpers

* Rename Col -> Column throughout

* Rename H -> Horizontal and V -> Vertical throughout

* Add Markup_Experimental flag for all API methods and update all unit tests to run with and without the flag

* Re-add "Markup_Experimental" flag

* Add default bindable properties / test exclusions for new BindableObject types in core

* Add constructorHint to FuncConverter and Style for more clear experimental flag message

* Add default bindable property for RadioButton - fixes test AllBindableElementsInCoreHaveDefaultBindablePropertyOrAreExcluded failure

* Cross-Platform OS Theme APIs (#9958)

* Implement OnAppTheme

* Implement AppThemeColor

* Added tests

* Finishing up

* Implement UWP

* Xcode 11 and additional test

* Update Forms.cs

* Update ViewRenderer.cs

* Update ViewRenderer.cs

* Remove IAppThemeProvider

* Implemented RequestedThemeChanged

* Update WindowsBasePlatformServices.cs

* Bindable props and Android invalidate

* Update DefaultBindableProperties.cs

* Updates at runtime

* Review feedback part 1

* Implement VisualElement.OnRequestedThemeChanged

* UWP Dispatcher

* Add experimental flag

* ControlGallery restructure

* Update ViewRenderer.cs

* Update WindowsBasePlatformServices.cs

* iOS pre-13 fix

* AppTheme fix NRE (#10327)

* Various fixes

* Back to basics

* [Enhancement] Shapes (#9218)

* Added Shapes to Core and Core Gallery samples
Implemented basic Shapes on iOS

* Added basic shapes Android implementation

* Fixed UWP namespace conflicts

* Fixed WPF namespace conflicts

* Implemented basic shapes on UWP

* Fixed UWP Ellipse and Rectangle size issue

* Fixed Tizen Build

* Changes to fix the build errors

* Exclude shapes renderers from Tizen compilation

* Implemented LineCap and LineJoin in Android and iOS

* Implemented LineCap and LineJoin on UWP

* Fixed build error

* Updated Polygon sample

* Fixed UWP Build error (namespace conflicts)

* Fixed namespaces collision build error

* Added "Shapes_Experimental" flag

* Update UWP ShapeRenderer size logic

* Updated iOS and Android ShapeRenderer size logic

* Fixed UWP Build error

* Added WPF implementation

* Fixed Tizen Build error

* Added Shapes macOS implementation

* Fixed broken unit tests

* Use the same Shapes classes between UWP and WPF backends

* Fixed flipper macOS shape issue

* Changed Shape class to be abstract

* Added Polygon and Polyline unit tests

* Added more Shapes Unit Tests

* Moved Shapes to Xamarin.Forms.Shapes in Android, iOS and macOS

* Moved Shapes to Xamarin.Forms.Shapes namespace in Windows (UWP and WPF)

fixes #2452 (partially)
fixes #9178

* [Enhancement] Shapes (Path) (#9264)

* Added Path definition in Core (Shapes)
Implemented Path in Android and iOS

* Fixed Android build errors

* Fixed UWP Build

* Fixed WPF Build

* Implemented PathRenderer on UWP

* Added unit tests

* Fixed namespaces conflicts in Platform projects

* Changes to fix the build errors

* Implemented Path Transformations in Android and iOS

* Fixed Build error in WPF and UWP

* Implemented Path Transformations in UWP

* Fixed iOS Build error

* Changes to fix the Build (Path namespace conflict)

* More changes to fix the build error

* Fixed Windows Build errors

* Fixed Path size issue on UWP

* Added Shapes_Experimental flag

* Updated path sample

* Updated Android ShapeRenderer size logic

* Added Shape Aspect sample in Core Gallery

* Added more Shapes samples

* Updated UWP PathRenderer size logic

* Updated droid and iOS pathRenderer size logic (same behavior in all the platforms)

* Updated UWP ShapeRenderer

* Implemented Path in WPF Backend

* Fixed build error

* Initial Clip implementation in WPF and UWP (work in progress)

* Added Path implementation on macOS

* Added Clip implementation in Android, iOS and macOS

* Fixed broken unit tests

* Notify the change of Geometry if any of the child properties changed

* Added new sample clipping different views

* Fixed flipped shape issue on macOS

* Added support to Clip using EllipseGeometry, LineGeometry and RectangleGeometry in UWP

* Changed Shape class to be abstract

* Moved Shapes to Xamarin.Forms.Shapes in Android, iOS and macOS

* Moved Shapes to Xamarin.Forms.Shapes namespace in Windows (UWP and WPF)

* Fixed wrong property in LineGeometry

* Fixed build error

* Added Clip Performance sample in Core Gallery

* Update Matrix.cs

* Update RectangleGeometry.cs

* Update Xamarin.Forms.Platform.macOS.csproj

* Some duplicate classes

* Update PointCollectionTests.cs

* Update ImageButtonRenderer.cs

* Update Xamarin.Forms.Platform.iOS.csproj

* Update Xamarin.Forms.Platform.iOS.csproj

* Fixed tabs error

Co-authored-by: Samantha Houts <samhouts@users.noreply.github.com>

fixes #2452 (partially)
fixes #9178

* Add fluent DynamicResource markup helpers

* Add support for all IPaddingElement Elements to Padding markup helpers (was only Layouts)

* Make family first parameter of Font markup helper (reduces the need to use named parameters across all FontElement extensions)

* Add Stars(double) markup helper for Grids

* Add RelativeLayout markup helpers

* wip Add RelativeLayoutTests

* Add RelativeLayout markup helpers done

* Add BindableLayout markup helpers

* wip Add MultiBind and MultiConverter support to markup helpers

* - Add multiconverter markup helpers
- Improve Bind markup helpers: add multibinding, make more strongly typed, remove converterParameter where unused
- wip Add unit tests for multiconverter and multibind

* wip Add unit tests for multibind

* Move MultiBind helpers + tests to separate files
wip Complete MultiBind unit tests

* wip Add unit tests for MultiBind markup helpers

* Add unit tests for MultiBind and MultiConvert markup helpers

* Add overloads for Bindable Layout markup helpers that take a Func<object> instead of a DataTemplate

* move C# Markup out of forms with internalsvisibleto, eliminate reflection

* Markup API: build against Forms 5 NuGet, remove experimental checks, change namespace to Xamarin.CommunityToolkit.Markup, add TODO comments for inaccessible IPaddingElement

* Build against Forms 5 NuGet, change namespace to Xamarin.CommunityToolkit.Markup.UnitTests, remove experimental flag testing. add TODO comments for inacccessible API's

* Add PR link to TODO comment

* Update to Forms NuGets that have public IPaddingElement
Get unit tests working and succeeding except for issue in Forms

* Bring unit tests to 100% code coverage
Cleanup mocks and remove all unused code from them
Remove all unnecessary namespace usings

* prefix Markup top-level folders with Xamarin.CommunityToolkit.

* add Xamarin.CommunityToolkit.Markup.sln, eliminate Markup subfolders, fix notimplemented exception in MockPlatformServices

* include stylecop.json in Markup project

* add comment with Forms NuGets download url to project files

* add prefix Xamarin.CommunityToolkit. to namespaces and assembly names where missing

* add package settings, license and icon to markup project

* add MarkupSample solution

* fix android build errro due to max path length (remove solution folder)
complete MarkupSample

* remove dependency on internal Forms PaddingElement and FontElement classes

* add temporary msbuild target for downloading NuGets from Forms PR

* add markup to ci

* fix markup project folder names in ci

* fix markup temporary NuGet download in ci

* fix markup unit test project for ci

* use NuGets from PR as merged into Forms 5.5.0 branch
fix tests that fail due to Forms PR 12689 not yet merged

* remove experimental wrapper from markup unit tests
align markup unit test project packagereferences to xct unit test project

* fix all code formatting warnings where applicable
suppress remaining code formatting warnings with justification where not applicable

* add warning codes from GlobalSuppressions.cs to NoWarn in project files

* fix Forms version warning
revert adding warning codes in project files

* ci run all tests in single task

* align markup csproj to XCT csproj for same type of debug info in release package

* update forms version in markup sample

* update to Forms 5.0.0.1709-pre4
remove custom Forms NuGet download targets
update unit tests for Forms fix fix xamarin/Xamarin.Forms#12689

* Markup package version  to 1.0.0-pre4
Markup sample to Markup 1.0.0-pre4 and Forms 5.0.0.1709-pre4

* MarkupSample: update Markup to 1.0.0-pre5, update Fody, update docs link to XCT content, fix iOS like button, suppress stylecop rules that do not apply to declarative markup

* MarkupSample: fix StyleCop warnings

* MarkupSample UWP set launch view size

Co-authored-by: Gerald Versluis <gerald.versluis@microsoft.com>
Co-authored-by: Javier Suárez <javiersuarezruiz@hotmail.com>
Co-authored-by: Vincent Hoogendoorn <dev@vincenth.net>
Co-authored-by: Vincent Hoogendoorn <vincenth@workstreampeople.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a/CsharpMarkup API-change Core hacktoberfest 🍻 roadmap t/enhancement
Projects
No open projects
v4.6.0
  
Done
Development

Successfully merging this pull request may close these issues.

None yet