{"id":13713042,"url":"https://github.com/matthewrdev/Xamarin.Forms.GridLocationExtension","last_synced_at":"2025-05-06T22:32:20.937Z","repository":{"id":78166167,"uuid":"323519618","full_name":"matthewrdev/Xamarin.Forms.GridLocationExtension","owner":"matthewrdev","description":"Specify grid locations by name for simpler, more maintainable XAML.","archived":false,"fork":false,"pushed_at":"2020-12-22T22:52:21.000Z","size":615,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-13T23:32:53.760Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/matthewrdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-22T04:23:52.000Z","updated_at":"2021-10-28T19:39:56.000Z","dependencies_parsed_at":null,"dependency_job_id":"b2dc70fb-0b22-484a-bc69-bd824e0b125f","html_url":"https://github.com/matthewrdev/Xamarin.Forms.GridLocationExtension","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewrdev%2FXamarin.Forms.GridLocationExtension","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewrdev%2FXamarin.Forms.GridLocationExtension/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewrdev%2FXamarin.Forms.GridLocationExtension/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/matthewrdev%2FXamarin.Forms.GridLocationExtension/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/matthewrdev","download_url":"https://codeload.github.com/matthewrdev/Xamarin.Forms.GridLocationExtension/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252779444,"owners_count":21802951,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T23:01:26.449Z","updated_at":"2025-05-06T22:32:20.077Z","avatar_url":"https://github.com/matthewrdev.png","language":"C#","funding_links":[],"categories":["UI"],"sub_categories":[],"readme":"# Xamarin.Forms Grid Markup Extension\n\n**🚨Experimental🚨**.\n\nSpecify grid locations by name for simpler, more maintainable XAML.\n\n**Before**\n\n```\n\u003cLabel Grid.Row=\"0\" /\u003e\n```\n\n**After**\n\n```\n\u003cLabel Grid.Row=\"{local:GridLocation titleRow}\"/\u003e\n```\n\nSee:\n\n * [GridLocationExtension](GridLocationMarkupExtension/GridLocationExtension.cs)\n * [GridSpanExtension](GridLocationMarkupExtension/GridSpanExtension.cs)\n\n ![Using the GridLocation and GridSpan markup extensions](img/example-image.png)\n\n## The Problem With Grids In Xamarin.Forms\n\nGrids, while powerful, have one fundamental drawback; we place controls using 0-based indices. Consider the following code:\n\n```\n\u003cGrid\u003e\n    \u003cGrid.RowDefinitions\u003e\n        \u003cRowDefinition Height=\"Auto\"/\u003e\n        \u003cRowDefinition Height=\"2\"/\u003e\n        \u003cRowDefinition Height=\"*\"/\u003e\n    \u003c/Grid.RowDefinitions\u003e\n\n    \u003cLabel Grid.Row=\"0\" /\u003e \u003c!-- Title label --\u003e\n    \u003cContentView Grid.Row=\"1\" /\u003e \u003c!-- Content Divider--\u003e\n    \u003cStackLayout Grid.Row=\"2\"/\u003e \u003c!-- Content --\u003e\n    \u003cActivityIndicator Grid.RowSpan=\"3\" /\u003e \u003c!-- Loading Indicator that covers all rows --\u003e\n\n\u003c/Grid\u003e\n```\n\nEach time we place a control in the grid, we do so using a 0-based location. This has a few problems:\n\n * Firstly, we can accidentally use an index not declared in the `RowDefinitions/ColumnDefinitions` of the grid, creating a rendering bug.\n * Secondly, if we add or remove a row/column, we now need to update the `RowDefinitions/ColumnDefinitions` and all affected indices in the grid.\n * Lastly, it is difficult to tell if we have correctly placed our control in the grid when looking at syntax such as `Grid.Row=\"1\"`. There is a significant amount of thinking required to validate this location.\n\nTo solve these issues, this repository introduces two new markup extensions that allow grid locations to be referenced by name:\n\n * Use the `GridLocationExtension` to lookup the index of a named row or column in XAML: `Grid.Row={local:GridLocation namedRow}`.\n * Use the `GridSpanExtension` to calculate the span between two named rows or columns in XAML: `Grid.Row={local:GridSpan From=startRow, To=endRow}`.\n\nThese extensions require that each row and column definition includes an `x:Name` attribute to expose it to the extension. For example: `\u003cRowDefinition x:Name=\"contentRow\" Height=Auto/\u003e`.\n\nHere is an example these extensions applied to the previous code sample:\n\n```\n\u003cGrid\u003e\n    \u003cGrid.RowDefinitions\u003e\n        \u003cRowDefinition x:Name=\"titleRow\"  Height=\"Auto\"/\u003e\n        \u003cRowDefinition x:Name=\"dividerRow\" Height=\"2\"/\u003e\n        \u003cRowDefinition x:Name=\"contentRow\" Height=\"*\"/\u003e\n    \u003c/Grid.RowDefinitions\u003e\n\n    \u003cLabel Grid.Row=\"{local:GridLocation titleRow}\" /\u003e \u003c!-- Title label --\u003e\n    \u003cContentView Grid.Row=\"{local:GridLocation dividerRow}\" /\u003e \u003c!-- Content Divider--\u003e\n    \u003cStackLayout Grid.Row=\"{local:GridLocation contentRow}\"/\u003e \u003c!-- Content --\u003e\n    \u003cActivityIndicator Grid.RowSpan=\"{local:GridSpan From=titleRow, To=contentRow}\" /\u003e \u003c!-- Loading Indicator that covers all rows --\u003e\n\n\u003c/Grid\u003e\n```\n\nThere are a few benefits here:\n\n * Each row/column definition is now documented via the `x:Name` attribute.\n * As rows/columns are now resolved at runtime via the `GridLocation` extension, we can freely move and delete rows/columns without needing to readjust indices and spans.\n * We can use `GridSpan` extensions `From` and `To` to easily calculate the correct spans through names. This reduces code complexity and makes it very clear what the intended behaviour of a span is.\n\nIf you like this work and would like to see it continue, please raise an issue to start a discussion. 😊\n\n## Disclaimer\n\nWhile stable and tested, it is **not** recommended that you use this code in your production apps for the following reasons:\n\n * These extensions do not have complete API documentation.\n * The extensions have no error logging to assist you in diagnosing runtime issues.\n * The extensions use reflection to perform the location and span calculations. This may have adverse runtime performance impacts.\n * The extensions execute a Xamarin.Forms internal API with the use of reflection. Unless Xamarin.Forms exposes the relevant APIs, this methodology may break at any point in the future.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatthewrdev%2FXamarin.Forms.GridLocationExtension","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatthewrdev%2FXamarin.Forms.GridLocationExtension","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatthewrdev%2FXamarin.Forms.GridLocationExtension/lists"}