A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
.NET developers are excited with the reality of .NET Multi-platform App UI (.NET MAUI)—the evolution of modern .NET cross-platform developer technology stack. With stable tooling and a rich ecosystem, .NET MAUI empowers developers to build native cross-platform apps for mobile/desktop from single shared codebase, while inviting web technologies in the mix.
While it may take a long flight to reach the sands of MAUI island, developer excitement around .NET MAUI is quite palpable with all the created content. Like the grains of sand, every piece of news/article/documentation/video/tutorial/livestream contributes toward developer experiences in .NET MAUI and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here’s what is noteworthy for the week of March 18, 2024:
.NET is constantly evolving and the next big milestone is already cooking. Following the successful launch of .NET 8 a few months back, .NET is back on its annual release cycle—say hello to .NET 9 with Preview 2 now out. With some community feedback, the now comprehensive release notes highlight the enhancements in .NET 9 Preview 2.
Set to be released at .NET Conf in November 2024, work is underway toward the next big .NET release. The most important focus areas for .NET 9 are cloud-native and intelligent app development. Developers can expect significant investments in performance, productivity and security, as well as advancements across the .NET platform. Tooling will get better with Visual Studio and Visual Studio Code with the C# Dev Kit, and cloud deployments will get easier using Azure services. Microsoft will continue to work with developers looking for ways to use C# skills to build next generation of intelligent apps, and to rapidly invest in AI.
Along with .NET 9 Preview 2 release, come fresh new bits for .NET MAUI, ASP.NET Core, libraries and runtime updates—.NET 9 promises great things for the ecosystem.
Developer excitement is palpable with .NET MAUI—the evolution of cross-platform .NET development stack reaching mobile/desktop from a shared codebase. The .NET MAUI team hosts monthly Community Standup livestreams to celebrate all things .NET MAUI and provide updates—a wonderful way to bring the developer community together. David Ortinau hosted the latest standup, with special guest Bret Johnson—the March .NET MAUI Community Standup, combining .NET MAUI with .NET Aspire.
After the usual .NET MAUI community recap, it was time to dive into the topic of the month—a match made in the clouds. .NET Aspire is an opinionated, cloud-ready stack for building observable, production ready, distributed applications. Cloud-native apps often consist of small, interconnected microservices rather than a single monolithic code base—popular services include web frontend, APIs, databases, messaging, caching and more. Native mobile and desktop apps written with .NET MAUI do not live in silos—they are often backed by cloud services for APIs or companion web apps.
Bret showed off the possibilities of combining the best of .NET Aspire with .NET MAUI—developers get to easily leverage RESTful services and build companion .NET MAUI apps with templates, configuration and telemetry. The future is bright when modern cloud native .NET apps are combined with the convenience of .NET MAUI cross-platform apps—cheers to developer flexibility.
.NET MAUI is the evolution of modern .NET cross-platform development stack, allowing developers to reach mobile and desktop form factors from a single shared codebase. With increased stability and a rich ecosystem, there are lot more developers building cross-platform apps with .NET MAUI—many seeking consistent building experiences from Windows/macOS/Linux developer machines. The answer is Visual Studio Code and Maddy Montaquila joined Robert Green on a recent VS ToolBox shows to talk through developer experiences—getting started with .NET MAUI in Visual Studio Code.
Visual Studio Code is the uber-popular lightweight code editor that works seamlessly across Windows/macOS/Linux. While Visual Studio continues to be the rich IDE on Windows, VS Code represents the engineering consolidation of developer tooling across platforms—the lightweight editor brings a rich Extensions ecosystem and provides consistency of developer experiences. Developers building cross-platform apps with .NET MAUI are empowered with the new .NET MAUI VS Code Extension.
Maddy walked through how to get started with the Extension, along with needed dependencies and showcased the developer workflows toward building native apps across platforms. Developers are able to debug cross-platform/platform-specific code and run their .NET MAUI apps on any simulator or connected devices, based on target platforms. VS Code is now the preferred cross-platform editor for many .NET developers, and the new .NET MAUI VS Code Extension promises developer productivity.
.NET MAUI is built to enable .NET developers to create cross-platform apps for Android, iOS, macOS and Windows, with deep native integrations, platform-native UI and hybrid experiences that extend the reach of Blazor/JS web UI technologies. Blazor and .NET MAUI are almost made for each other, sharing the exact .NET runtime—Blazor apps hosted inside .NET MAUI apps enjoy full native platform integration. Blazor Hybrid apps, as they are called, enable a lot of code sharing across web and native apps on mobile/desktop. Daniel Hindrikes has started building a new Blazor Hybrid app from scratch and second of the video series is up—saving data and creating tests for an activity tracker app with .NET MAUI and Blazor.
Blazor is welcome on mobile/desktop apps with .NET MAUI and developers are enabled to share a lot between web/native apps—C# code, Blazor components, JS Interop and CSS styles. In the second episode of the series, Daniel picks up from where he left off—setting up a service layer for data persistence to a local database using LiteDB. Daniel also gets down to real business—writing unit tests to have more confidence in the codebase. For anyone looking to get real-world inspiration toward building Blazor Hybrid apps, this series from Daniel looks very promising—more awesomeness to follow.
Visual Studio App Center brings together multiple common services into a DevOps cloud solution—developers can use App Center to build, test and distribute native/cross-platform apps across platforms. Once deployed, developers can also monitor the status and usage of the app using Analytics and Diagnostics services provided by VS App Center. Most good things come to an end eventually, and there is sad news for App Center fans—Visual Studio App Center is scheduled for retirement on March 31, 2025.
While a good solution, the retirement of VS App Center should not come as a surprise for most developers in the Xamarin/.NET MAUI world. VS App Center did not get around to supporting .NET MAUI officially and feature development has been slow. The reality is, for much needed DevOps and app publication/distribution services, there are simply much more sophisticated solutions, like Azure Pipelines, GitHub Actions, Apple TestFlight or Google Play Console.
While VS App Center will continue working with full support until next March, developers are encouraged to start migrations—the retirement announcement outlined several better alternative solutions to VS App Center features. Native or cross-platform apps need reliable services for CI/CD build/test pipelines, publishing/distribution modes and analytics/diagnostic services—the end of era for VS App Center should point developers to better modern solutions.
That’s it for now.
We’ll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>The immense growth of ecommerce wouldn’t be possible without payment processing technology. Can you imagine having to process each online customer transaction using an old school point of sale system or credit card processor?
But just like other technologies we use when building websites and apps, there are lots of options to choose from. So which one should you use when setting up your next ecommerce site? You could always opt for PayPal or Stripe since they’re the most popular. But are they really the best choice?
In this post, we’ll take a look at the 14 traits to consider when choosing a payment processor and then go over various options.
The payment processor you integrate with your shop can seriously impact the user experience and, consequently, the conversion rate and sales generated on your ecommerce site.
Here are some of the most popular payment processing options today:
And here are some payment processors that are rising in popularity. Most of them have positive ratings on Trustpilot, by the way:
Before you settle on one, ask yourself the following questions as you consider the options:
Whenever you build a website or app, you have a checklist of security measures to implement before it can launch. Even though you’re not building the payment processing technology, you still have to make sure it adheres to those strict protocols (and more).
The easiest way to do this is by finding a payment processor that is PCI DSS compliant. This means the software has been validated against 12 security protocol requirements. These include things like:
If a security breach were to take place at checkout, you won’t be able to pass the blame onto the payment processor. You might be able to internally, but definitely not with your customers. If it took place on your site or in your app, then they’re going to hold you responsible.
So choosing a payment processor that prioritizes security and is PCI DSS compliant is a must.
Another way to secure the payment gateway is with fraud protection. There are different ways you’ll see this implemented in a payment gateway:
Card Verification Value (CVV) is that three- or four-digit numeric code that appears on the back or front of a credit card. This isn’t a foolproof way to prevent fraud since someone could have stolen the actual credit card. However, for a fraudster who only has the credit card number, they won’t be able to complete the transaction without the verification code.
Address Verification Service (AVS) is when the processor requires the customer to fill in their billing address as well as their ZIP code. If it doesn’t match the data the credit card company or bank has on file for the customer, the transaction is rejected.
3D Secure is another way that payment processors authenticate that the customer is who they say they are. It’s basically two-factor authentication that takes place during checkout. After the customer logs in or enters their payment details, they’re sent a verification code either via SMS or email.
There are other fraud protection measures a payment processor might use, but these are the most common ones.
There isn’t a whole lot of data on the fastest payment processors online, so before officially committing to one, give it a try for yourself. There are a few things to look out for when it comes to speed.
The first is how quickly the cart and checkout pages load. Just as with the rest of your website, it shouldn’t take more than a couple seconds.
Also check to see how fast and easy the checkout form is to use. When customers use the tab key to move from field to field, it should happen instantaneously. No fields should be skipped either.
Lastly is how quickly and smoothly the processing happens. The last thing you want is for customers to fill everything out, hit the “Submit” or “Purchase” key, only to not know if the transaction is processing or how long it will take.
The flow from your website to checkout should be as seamless as possible. If you’ve built a responsive and mobile-first website, then you’ll want a payment gateway that looks and feels the same way.
Again, I’d recommend giving the payment gateway a try for yourself. While they might claim it’s responsive, there might be certain aspects of it that don’t feel right on smaller screens.
For instance, I recently was checking out on my smartphone and couldn’t get to the final ZIP code field for some reason. I wasn’t able to scroll down to it nor could I use the tab arrow to get me there. I ended up having to turn my computer on and complete my purchase that way.
Some payment processors give you their out-of-the-box software and say, “Here ya go!” And that’s it. You’ll of course be able to choose which payment options to display. But what about when it comes to the structure of the checkout page or the form fields?
No out-of-the-box solution will be okay for every customer. Instead, you want to find a payment gateway that you can customize. In addition to modifying the payment methods, the layout of the page, the form fields and other features, you should be able to brand and edit your ecommerce emails.
If you’ve designed a comfortable, convenient and streamlined experience for customers up to this point, don’t let it fall apart with an email branded with the payment processor’s name. Or with a form that’s too long to fill out and with irrelevant fields. Or with a process that doesn’t allow guests to checkout.
You know your users better than anyone. Use software that enables you to design this last step in the process just for them.
Another way your payment gateway might disrupt the checkout experience is if you send customers to a different website to complete their transaction. If the payment gateway is super recognizable, your shoppers might be OK with checking out there. If it’s not, you could see an increase in user abandonment rates.
So take a look at how your payment processor handles this.
Is there a non-hosted option where the payment gateway is integrated directly into your website? This will create the most seamless experience for your shoppers as they’ll stay right where they are to pay.
If there is only a hosted option, what does it look like—is it an embedded iFrame on your site or does it take users to a new domain? Will customers find the processor’s branding instead of your own? Will the look and feel of it completely conflict with the site or app you built?
If you don’t think it will cause too much friction, then this option might work.
There are a couple of things to look for here. For starters, you’ll want to make sure the payment processor allows you to sell physical products, digital products, services or whatever it is you sell.
Also look to see if they support recurring payments, memberships and auto-renew product sales as well. If you plan on generating recurring revenue, you’ll need a processor that makes it easy to do so.
Different stores and brands have different needs. For example, if you’re building an ecommerce site for a brick-and-mortar store, it would be nice to find a payment processor that offers different technologies, like an online payment gateway as well as physical point-of-sale systems.
It’s not just the types of payment processing you should consider either. Think about what sorts of tools and features will help you or your client better manage their orders and payments. For example, you might need one that can handle chargebacks and refunds with ease.
The first piece of software your payment gateway needs to integrate with is your content management software. I don’t think you’ll have much of a problem with that. However, I would check to see if there’s a direct connection between your CMS and the gateway. If not, review the integration process to make sure it’s not overly complicated. You want there to be a strong and stable connection between the two.
Then figure out what other software needs to integrate with your payment gateway. For example:
By integrating other apps with your payment gateway, you can streamline the flow of payment and order information to other aspects of the business that need it.
It doesn’t happen as much nowadays, but I remember in the past when I’d have issues trying to pay with an American Express card on some websites and apps. It probably wasn’t the vendor’s choice. They most likely were using a payment processor that didn’t support those cards.
So that’s something to look up if your client or employer wants certain credit cards to be accepted.
That’s not all. You’ll want to dig deeper into what other payment methods are offered. For example, you might find that they work with Alipay and PayPal. If you want to accept ACH Direct Debit, that’s something else to look into.
One other thing to consider is if they accept mobile wallet payments. While these payments are commonly made in store, websites and apps should be able to accept them as well. If you want your shop to access more revenue opportunities, choosing a payment processor that works with Apple Pay or Google Pay is a good idea.
Check to see which countries and currencies are supported. This list will first tell you if you’re even eligible to use this service. Not every payment processor is everywhere. PayPal, for instance, has a blacklist of countries it won’t do business with either because the market isn’t big enough or they have problems with fraud.
This list will also tell you what sort of market penetration you can expect. If you’re building an ecommerce site that’s meant to be for global shoppers, you’ll need a payment method that enables the greatest number of customers to buy from it.
Before you go scratching a payment processor off of your list, though, take some time to really get to know your target users. They might not even live in the areas where you’re unable to take payments from.
Payment processors aren’t free to use. Some are free to set up while others you have to pay to use. On top of that, there are other fees to consider, like:
Your fee structure may also differ depending on the volume of sales your site or app does. So pay close attention to that if you expect your store to scale rapidly.
Once you’ve settled on some payment processor options, do a search for the company’s name plus “fees.” You’ll find a page that lists out all the nitty-gritty details you need to know.
Every company is going to tell you that they offer fast and helpful customer support. If you want to know the truth about what it’s like to use support when you need it, go to Trustpilot and do a search for the company’s name.
When researching this article, I found that some of the most popular solutions (with the exception of Stripe) had abysmal ratings and reviews when it came to customer service. The newer and lesser known options interestingly enough had much fewer complaints.
So if that matters to you, do your research ahead of time.
Some payment processors impose minimum and maximum limits. One reason why this matters is because you won’t want to get stuck paying a steep minimum fee when your site or app isn’t generating any sales.
Another reason is because a maximum limit can hamper your ability to scale your business and its sales. You need a payment gateway that works well—even when there’s tons of traffic flowing through it—along with one that works no matter how much you sell through it.
There are two aspects of payment processing to focus on as you go through the decision-making process. First, is the payment processor company trustworthy? Second, is the payment gateway software reliable and can it do everything you need it to do?
The last thing you want to do is to settle on a payment processor, only to find that it keeps you from selling to a specific market or it takes too big of a chunk out of each sale. So once you find a few solutions you like the look and sound of, take them through the 14 questions above and see how they pan out. That should help you find the right one for the digital product you’ve built.
This blog was prepared by Suzanne Scacca in their personal capacity. The opinions or representations expressed herein are the author’s own and do not necessarily reflect the views of Progress Software Corporation, or any of its affiliates or subsidiaries. All liability with respect to actions taken or not taken based on the contents of this blog are hereby expressly disclaimed. The content on this posting is provided “as is” with no representations made that the content is error-free.
]]>I write this article as a deep admirer of Progress Telerik for its products, extraordinary graphical interfaces, high-performance Grids, document manipulation libraries, report editor, and an immense number of components for various languages and platforms, in addition to the quality of support and best of all: listening to its customers.
The fact is, here I am, now a Progress Champion writing for the Progress Telerik blog because I was a customer first—and I’m sharing from that experience. My admiration is technical because, before I met Telerik, I had already developed more than 200 components using VB 5/6 (ActiveX DLL) as a developer, consultant and CEO at Menphis, based in Brazil.
The image below is the face of my main product at the time, Advocati Desktop, before using Progress Telerik:
Main screen from Advocati Desktop
Sorry, but …
Meme from Internet/Disney movie
With all this experience, I grew professionally, reaching unprecedented know-how and know-why because, with Advocati Desktop, I gathered requirements, developed, implemented, offered support, and worked simultaneously as an IT Administrator using the system I had designed—a unique experience.
When Menphis started working with C# (WinForms and ASP.NET WebForms), we found in Telerik the same quality we sought to create when making our products.
In this way, the choice for Telerik was automatic because other competitors did not offer the same quality and diversity of products.
We built the web version of Advocati Desktop with Telerik UI for ASP.NET AJAX. The demo is accessible via the link on my digital card: https://jsmotta.com.br.
Customers’ CRUD
With the COVID-19 pandemic, I entered a new phase in my career. I started working for other companies as an employee or freelancer, providing services to large companies in Brazil and internationally.
In these companies where I worked and also in the consulting time of Menphis, I always observed that developers have this idea that they need to create their own components, just like me. However, the burden is enormous because always keeping up to date and working with the system for an extended period generates a technological debt that no one wants for themselves.
I also observed that large companies’ system developments could reduce their time drastically by switching to a professional component library. After all, instead of using RAD (rapid application development) tools with configuration, operation, performance and scalability like Telerik products, much time was wasted trying to solve behavioral problems of open-source (“free”) components, which end up being much more expensive because they do not have support or updates. An economy that is not at all intelligent!
I call on all Project Managers, CTOs, CIOs and those interested in technology to consider Telerik DevCraft, which, in addition to having a coherent and customizable look, also has the benefit of being easily updated to the most recent versions of programming languages/tools such as WinForms, WPF, React, Angular, Vue, jQuery, ASP.NET Core, Blazor, .NET MAUI, etc. The license is perpetual, and you get one year of free upgrades. Stay up to date with new versions and robust support by renewing your license, which comes discounted when done annually.
To reinforce my point, with Telerik, you save development time with easy-to-handle components that come with functional code, demos and forums; that deliver high performance; that are scalable, with unique features and attractive UIs; and, above all, that will add to your product’s or service’s credibility by using the same technology that Microsoft, IBM and NASA (among other giants) use globally.
Check all Telerik products at https://www.telerik.com/all-products
I encourage you to give it a try—download a free trial today.
]]>A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
.NET developers are excited with the reality of .NET Multi-platform App UI (.NET MAUI)—the evolution of modern .NET cross-platform developer technology stack. With stable tooling and a rich ecosystem, .NET MAUI empowers developers to build native cross-platform apps for mobile/desktop from single shared codebase, while inviting web technologies in the mix.
While it may take a long flight to reach the sands of MAUI island, developer excitement around .NET MAUI is quite palpable with all the created content. Like the grains of sand, every piece of news/article/documentation/video/tutorial/livestream contributes toward developer experiences in .NET MAUI and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here’s what is noteworthy for the week of March 11, 2024:
The .NET MAUI Community Toolkit is an open-source library serving as a companion to .NET MAUI development, offering developers a rich set of controls, converters and helpers designed to accelerate app development. With a focus on community-driven innovation and developer productivity, the .NET MAUI Community Toolkit has become an indispensable tool for developers looking to enhance .NET MAUI app development. Kym Phillpotts reflected on last year’s journey and wrote up an article—.NET MAUI Community Toolkit Highlights for 2023.
The .NET MAUI Community Toolkit GitHub repository has evolved into a dynamic hub of activity, engaging more than 40 contributors who have collectively pushed the project forward. Developer feedback, suggestions and code contributions have been instrumental in shaping the toolkit into a more powerful and efficient resource for .NET MAUI developers.
Some of the highlights for .NET MAUI Community Toolkit over 2023 include features delivered through nine releases and 260 commits. Some of the substantial capabilities added to the .NET MAUI Community Toolkit include the Media Element control, Windows Maps integration, speech recognition and speech to text, FolderPicker and FileSaver, Keyboard Extensions, App Theming APIs and .NET 8 support.
Solid documentation and an impressive number of NuGet package downloads signify the widespread adoption and trust in the toolkit—kudos to all contributors for making the .NET MAUI Community Toolkit an integral companion for .NET MAUI developers. Upwards and onwards for developer productivity.
Many modern mobile apps deal with media files—there are innumerable use cases of using photos or videos to light up workflows in iOS/Android. Thankfully for .NET MAUI developers, working with media is easy, thanks to well-engineered cross-platform Media Picker abstraction. Empowering mobile users to work seamlessly with photos/videos is a nice luxury for developers, and Leomaris Reyes wrote up an article to help—getting started with Media Picker in .NET MAUI.
The first step toward with working with media files is platform-level permissions. Leomaris walks through what developers need to wire up for Android and iOS. Media Picker’s capabilities are made possible by the IMediaPicker interface, which enables users to capture or select photos/videos on their devices. The Microsoft.Maui.Media namespace contains the default implementation of the IMediaPicker interface, which developers can invoke easily—there are async methods to pick/capture photos or video.
Leomaris walks through how developers can work with Media Picker in .NET MAUI—capturing photos/videos or picking a media file from library, and easily displaying it in UI. The Media Picker abstraction is a wonderful benefit for .NET MAUI developers, making it easy to empower users to work with media files.
.NET MAUI is built to enable .NET developers to create cross-platform apps for Android, iOS, macOS and Windows, with deep native integrations, platform-native UI and hybrid experiences that extend the reach of Blazor/JS web UI technologies. Blazor and .NET MAUI are almost made for each other, sharing the exact .NET runtime—Blazor apps hosted inside .NET MAUI apps enjoy full native platform integration. Blazor Hybrid apps, as they are called, enable a lot of code sharing across web and native apps on mobile/desktop. Daniel Hindrikes has started building a new Blazor Hybrid app from scratch and first of the video series is up—getting started building an activity tracker app with .NET MAUI and Blazor.
Blazor is welcome on mobile/desktop apps with .NET MAUI and developers are enabled to share a lot between web/native apps—C# code, Blazor components, JS Interop and CSS styles. In the first episode of the series, Daniel does a great job explaining the promise of Blazor Hybrid apps, before getting down to setting things up—creating projects and building the first reusable UI components across platforms. The common trick to reuse the same Blazor UI across web and native apps is to put the shared components in a separate Razor class library—and reference the same from .NET MAUI native app and Blazor web app. For anyone looking to get real world inspiration toward building Blazor Hybrid apps, this series from Daniel looks very promising—more awesomeness to follow.
.NET MAUI is the evolution of modern .NET cross-platform development stack, allowing developers to reach mobile and desktop form factors from single shared codebase. The present reality for many apps, however, may be Xamarin or Xamarin.Forms. A migration strategy is needed to move things forward. Lance McCarthy has been busy trying to migrate a sample Telerik CRM app and joined an aging developer to share experiences on the .NET Dev Show—DevOps and Publishing for .NET MAUI Apps.
After a bit of troubleshooting with .NET MAUI development, the discussion turned to the Telerik Art Gallery CRM app—a wonderful showcase app available in iOS/Android/Windows App Stores that is written with Xamarin.Forms and source code up on GitHub.
With some careful migration, Lance was able to reuse much of the C#/XAML code from Xamarin.Forms in .NET MAUI—but developer responsibility does not stop with app development. Any serious app development/deployment would benefit from modern DevOps—a properly configured CI/CD pipeline can make app package builds/distribution much easier.
Lance is fond of GitHub Actions for .NET MAUI DevOps and stepped through YAML workflows to set up build automation upon code commits—a one-time process can configure a pipeline for builds reaching various platforms. With configurable environment variables and efficient management of keys/credentials, the benefits of DevOps powered by GitHub Actions is very apparent for .NET MAUI apps.
From covering migration strategies to moving code and ending in DevOps, Lance has now done a series of episodes on the .NET Dev Show—a wonderful showcase of moving a real-world app from Xamarin to .NET MAUI.
.NET is the free, open-source, cross-platform framework for building modern apps and powerful cloud services. Developers building with .NET enjoy solid frameworks, stable tooling and rich ecosystems—there is plenty of productivity boost to build, test and deploy modern apps across various platforms with .NET.
Modern .NET is not just for big enterprise apps, though, and Maddy Montaquila made a short video—how .NET MAUI helps get mobile/desktop apps to market faster for startups.
With .NET MAUI, developers can target mobile and desktop form factors from a single shared codebase. Between iOS/Android for mobile and Windows/macOS for desktop, .NET MAUI can boast wide platform reach—with increased platform/tooling stability, developers are finding more enticement to build cross-platform apps with .NET MAUI. For smaller companies just starting out, .NET MAUI presents an opportunity to reach maximum number of users, while leveraging a single shared codebase and reuse of .NET developer skills.
Developers have the flexibility to write .NET MAUI app UI in C#/XAML or reuse web investments written with Blazor—the end result is always a native cross-platform app with full-platform API access. With easy code reuse across wide range of devices and optimized developer productivity, the .NET MAUI promise can be beneficial for startups looking to build modern cross-platform apps with maximum user reach.
That’s it for now.
We’ll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
.NET developers are excited with the reality of .NET Multi-platform App UI (.NET MAUI)—the evolution of modern .NET cross-platform developer technology stack. With stable tooling and a rich ecosystem, .NET MAUI empowers developers to build native cross-platform apps for mobile/desktop from single shared codebase, while inviting web technologies in the mix.
While it may take a long flight to reach the sands of MAUI island, developer excitement around .NET MAUI is quite palpable with all the created content. Like the grains of sand, every piece of news/article/documentation/video/tutorial/livestream contributes toward developer experiences in .NET MAUI and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here’s what is noteworthy for the week of March 4, 2024:
.NET MAUI is built to enable .NET developers to create cross-platform apps for Android, iOS, macOS and Windows, with deep native integrations, platform-native UI and hybrid experiences that extend the reach of Blazor/JS web UI technologies. With increased stability and a rich ecosystem, developers are finding more enticement to build cross-platform apps with .NET MAUI. As more and more folks get started building cross-platform apps with modern .NET, James Montemagno has the perfect video series—.NET MAUI for beginners.
There might be a lot to take in for folks starting afresh with .NET MAUI cross-platform development for mobile/desktop apps. While learning is continuous, there should be no barrier to entry getting started with .NET MAUI.
In an eight-part video series, James begins with the basics and covers enough ground to get developers productive with .NET MAUI. Along the way, James covers installation, dependencies, C#/XAML visual tree, data binding, page navigation, platform features and shared resources—this series is a must-watch for anyone getting started toward successful .NET MAUI cross-platform development.
It is a good time to be a .NET developer, with multiple choices in technology stacks that take .NET across various platforms. Uno Platform is an open-source framework for building single codebase native mobile, web, desktop and embedded apps—all from the comfort of chosen IDE and C#/XAML. Uno Platform just had a major release, with big implications for the developer/designer divide—Uno Platform Figma plugin is now generally available.
Cross-platform app development has many considerations, but the design-to-code handoff can be a notorious bottleneck, consuming a staggering amount of time and causing unnecessary friction. The Uno Platform Figma plugin emerges as a natural extension of the Uno Platform, directly addressing this challenge by seamlessly integrating design and development workflows.
With Uno Platform for Figma, there is now a pragmatic solution for designers and developers, allowing both roles to stay in the tool of their preference. Designers use Figma and developers use the IDE of their preference—Visual Studio/VS Code or JetBrains Rider.
Uno Platform’s Figma plugin ensures that designers get to use their chops in Figma using Material Toolkit, and the generated app UI markup is 100% usable by developers—either as C# Markup or XAML. Uno Platform is welcoming .NET developers to go cross-platform and enabling more options together with .NET MAUI—this is great for the .NET ecosystem.
Content is king for most apps, and users need to be in charge. There is often a need to allow user manipulation of rich textual content—it can be tricky to balance usability with fidelity. Thankfully, there is UI help for .NET MAUI developers and Rossitza Fakalieva wrote up an article—manipulate rich text content in cross-platform apps with Telerik UI for .NET MAUI RichTextEditor.
Progress Telerik UI for .NET MAUI continues to be the most comprehensive UI component suite for all .NET MAUI apps—native performant UI controls that work across mobile and desktop platforms. The Telerik RichTextEditor UI for .NET MAUI enables users to create rich textual content through a WYSIWYG editor. It comes feature-rich with various editing capabilities, built-in Toolbar, text formatting/selection, font manipulations, hyperlink management, undo/redo editing actions, support for lists/indentation, image management and more.
Rossi walks through how to get started with the Telerik RichTextEditor within .NET MAUI projects and navigates through the nuances of the UI component with easy-to-follow code samples. With flexible styling API and easy customizations, .NET MAUI developers are enabled to put the user in charge—to confidently work with rich HTML content. Simplicity of user experience with developer flexibility—sounds like a win-win.
Gone Mobile is a long-running popular podcast that has evolved over time. Hosted by Jonathan Dick and Allan Ritchie, Gone Mobile covers all things mobile development, particularly with .NET MAUI, and delves into topics of cross-platform development, design and marketing of mobile apps. A recent episode should be a great listen for all .NET MAUI developers—anatomy of a mobile app.
In the episode, Jon and Allan discuss the process of building a mobile app, starting with the analogy of building a lightsaber at Disney. They explore the anatomy of a mobile app, including the use of MVVM architecture and the importance of gluing logic together. They also delve into navigation and the use of Shell in Xamarin.Forms/.NET MAUI.
The conversation then shifts to the benefits of using dependency injection in app development and the considerations for cross-platform development, with core services and platform implementations. They emphasize the importance of creating a base set of services and thinking outside the box when faced with UI design challenges. Mobile apps should solve business problems first, and allow development patterns to organically grow out of needs. Cross-platform mobile development is not easy—frameworks like .NET MAUI and the surrounding ecosystem aim to make mobile developers more productive.
With .NET MAUI, developers can target mobile and desktop form factors from a single shared codebase. While there is wide platform reach, .NET MAUI is also meant to provide developer flexibility—modern .NET cross-platform development can happen on variety of development stacks. While Windows and macOS are popular development platforms, Linux continues to gain popularity among a niche developer audience. There was a wonderful session at .NET Conf 2023 on unleashing modern cross-platform development with .NET 8 hosted by Luis Beltran and Bruno Capuano—creating .NET MAUI apps on Linux with Visual Studio Code.
Visual Studio Code is the uber-popular lightweight code editor that works seamlessly across Windows/macOS/Linux. VS Code brings a rich extensions ecosystem and developers building cross-platform apps with .NET MAUI are now empowered with the new .NET MAUI VS Code Extension.
Luis and Bruno demonstrate the essentials for starting the .NET MAUI development journey with the VS Code extension on Linux—from support requirements to steps toward getting everything installed on Linux. Through coverage of configuration, capabilities, limitations, demos and features, the duo provide a step-by-step guide toward the reality of .NET MAUI cross-platform development on Linux—a good place to start for hardcore Linux fans.
That’s it for now.
We’ll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>Empower your users to upload photos and videos to your iOS or Android application with the Media Picker in .NET MAUI.
Nowadays, it’s common to allow users to upload photos or videos to your apps. For example, banking applications let users upload essential documents for processing, saving them the time of going to a physical office. Providing this kind of experience to your apps adds a lot of value to the user experience. In this article, we’ll show you how to implement Media Picker with .NET MAUI in a straightforward way.
First, you’ll need to add some platform settings.
To make sure that your app runs smoothly on different versions of Android, you need to implement some general permissions as well as version-specific ones.
You have two ways to do that:
Go to Platform > Android > AndroidApplication.cs and set the following permissions:
CAMERA
as general permission.[assembly: UsesPermission(Android.Manifest.Permission.Camera)]
READ_EXTERNAL_STORAGE
and WRITE_EXTERNAL_STORAGE
permissions.[assembly: UsesPermission(Android.Manifest.Permission.ReadExternalStorage, MaxSdkVersion = 32)]
[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage, MaxSdkVersion = 32)]
READ_MEDIA_IMAGES
, READ_MEDIA_VIDEO
and READ_MEDIA_AUDIO
permissions.[assembly: UsesPermission(Android.Manifest.Permission.ReadMediaAudio)]
[assembly: UsesPermission(Android.Manifest.Permission.ReadMediaImages)]
[assembly: UsesPermission(Android.Manifest.Permission.ReadMediaVideo)]
[assembly: UsesFeature("android.hardware.camera", Required = true)]
[assembly: UsesFeature("android.hardware.camera.autofocus", Required = true)]
Go to Platform > Android > Android Manifest.cs and set the following permissions:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- Required only if your app needs to access images or photos that other apps created -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<!-- Required only if your app needs to access videos that other apps created -->
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<!-- Required only if your app needs to access audio files that other apps created -->
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
⚠ Note that these permissions comply with the same conditions explained in the first form, depending on the Android version.
<queries>
<intent>
<action android:name="android.media.action.IMAGE_CAPTURE" />
</intent>
</queries>
On iOS/Mac Catalyst, go to Platform > iOS or MacCatalyst > Info.plist and set the following permissions:
<key>NSCameraUsageDescription</key>
<string>This app needs access to the camera to take photos.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app needs access to microphone for taking videos.</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs access to the photo gallery for picking photos and videos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to photos gallery for picking photos and videos.</string>
✍️ To request permissions, it’s vital to consider the description attached to each one. These descriptions will be presented to the user during the request process.
For Windows, you don’t need any additional configuration.
Media Picker’s capabilities are made possible by the IMediaPicker interface, which enables users to capture or select photos and videos on their devices. The Microsoft.Maui.Media namespace contains the default implementation of the IMediaPicker interface, which you can access through the MediaPicker.Default property.
IMediaPicker includes a set of methods that return a FileResult
. These include the following:
For photos
PickPhotoAsync
: Allows users to open the media browser and select a photo from the available options.CapturePhotoAsync
: Responsible for opening the camera to take a photo.For videos
PickVideoAsync
: Allows users to open the media browser to select a video.CaptureVideoAsync
: Responsible for opening the camera to take a video.⚠ To ensure that permission checks and requests are handled automatically by .NET MAUI, all methods should be called on the UI thread.
Optionally, all of the aforementioned methods receive a MediaPickerOptions
parameter that allows you to add a title to the dialog to be displayed. Note that this only works on some operating systems.
It’s time to translate everything you’ve learned so far into code. The following graphic demonstrates the structure you’ll use to organize each detail in the code.
⭐ Now let’s implement the code, which allows you to open the Media Picker. This example uses the PickPhotoAsync()
method.
Let’s create a button and add an image control to display the selected photo.
<VerticalStackLayout Spacing="25" Padding="30,0" VerticalOptions="Center">
<Image x:Name="myImage"
BackgroundColor="Gray"
WidthRequest="300"
HeightRequest="300"
HorizontalOptions="Center" />
<Button
Text="Pick a picture"
Clicked="TakePhoto"
HorizontalOptions="Center" />
</VerticalStackLayout>
Let’s create an asynchronous method called TakePhoto
for this example. The following code allows the user to tap a button and select a photo from a dialog. You’ll achieve this with the PickPhotoAsync
method.
✍️ Note that all of this will be saved in the
Photo
variable, which is aFileResult
. Later, you’ll use this variable to obtain information about the selected image (which you can see in the next step).
private async void TakePhoto(object sender, EventArgs e)
{
FileResult photo = await MediaPicker.Default.PickPhotoAsync(new MediaPickerOptions
{
Title = "Select your photo"
});
// Here, add the code that is being explained in the next step.
}
Please keep in mind that adding the title with MediaPickerOptions is not mandatory.
As mentioned previously, the photo variable provides access to information such as the file name or full path among other details. This example uses the OpenReadAsync
method to retrieve the image.
In the previous blog section’s code, where it says // Here, add the code that is being explained in the next step
, insert the following code:
if (photo != null)
{
var stream = await photo.OpenReadAsync();
myImage.Source = ImageSource.FromStream(() => stream);
}
And that’s all! Let’s see the result!
Want to take a new photo instead of selecting an existing one? Add the code presented below. This example uses the CapturePhotoAsync
method to capture the photo.
private async void TakePhoto(object sender, EventArgs e)
{
FileResult photo = await MediaPicker.Default.CapturePhotoAsync();
if (photo != null)
{
// Getting the file result information
using Stream sourceStream = await photo.OpenReadAsync();
// Saving the file in your local storage
string localFilePath = Path.Combine(FileSystem.CacheDirectory, photo.FileName);
await sourceStream.CopyToAsync(File.OpenWrite(localFilePath));
}
}
I hope this article about using Media Picker to enable your users to upload photos and videos to your app was beneficial to you! I encourage you to implement these tips into your next project.
This article was based on Microsoft’s official documentation.
See you next time! ♀️
Use a component library in sync with .NET MAUI’s release cadence. Telerik UI for .NET MAUI comes with a free 30-day trial.]]>
A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
.NET developers are excited with the reality of .NET Multi-platform App UI (.NET MAUI)—the evolution of modern .NET cross-platform developer technology stack. With stable tooling and a rich ecosystem, .NET MAUI empowers developers to build native cross-platform apps for mobile/desktop from single shared codebase, while inviting web technologies in the mix.
While it may take a long flight to reach the sands of MAUI island, developer excitement around .NET MAUI is quite palpable with all the created content. Like the grains of sand, every piece of news/article/documentation/video/tutorial/livestream contributes toward developer experiences in .NET MAUI and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here’s what is noteworthy for the week of February 26, 2024:
It’s the start of a new year and the next big milestone for .NET is already cooking. Following the successful launch of .NET 8 a few months back, .NET is back on its annual release cycle—say hello to .NET 9 with Preview 1 now out. Along with the first bits for .NET 9, the .NET team also laid out broad plans for what’s ahead—the vision for .NET 9.
Set to be released at .NET Conf in November 2024, work is underway toward the next big .NET release. The most important focus areas for .NET 9 are cloud-native and intelligent app development. Developers can expect significant investments in performance, productivity and security, as well as advancements across the .NET platform. Tooling will get better with Visual Studio and Visual Studio Code with the C# Dev Kit, and cloud deployments will get easier using Azure services.
Microsoft will continue to work with developers looking for ways to use C# skills to build next generation of intelligent apps, and to rapidly invest in AI. With .NET 9 Preview bits available now, developers can start tinkering with what’s next—.NET 9 promises great things for the ecosystem.
.NET MAUI is built to enable .NET developers to create cross-platform apps for Android, iOS, macOS and Windows, with deep native integrations, platform-native UI and hybrid experiences that extend the reach of Blazor/JS web UI technologies. With increased stability and a rich ecosystem, developers are finding more enticement to build cross-platform apps with .NET MAUI. As the .NET 9 comes up on the horizon, cross-platform stack is getting some love as David Ortinau pointed out—there are fresh new bits out for .NET MAUI.
While there is a service release out to support .NET MAUI on .NET 8, all eyes are on the future—.NET MAUI bits now run on .NET 9 Preview 1. The team is continuing work on core fundamentals of the .NET MAUI SDK to improve overall stability—this includes expanding test coverage, end-to-end scenario testing and bug fixing. The .NET MAUI theme for the .NET 9 release is improved product quality across layout, control features, and reliability of tooling experiences such as setup, build, deploy, hot reload, debug and diagnostics. There are interesting work items under consideration including Swift Interop, custom cursors and more—upwards and onwards with .NET MAUI on .NET 9.
Cross-platform app development is not easy and developers need all the support—the .NET MAUI Community Toolkit is here to boost productivity. The .NET MAUI Community Toolkit is a curated collection of reusable elements for application development with .NET MAUI, thoughtfully created/maintained by the developer community. Developers should not reinvent the wheel on common UI needs and Leomaris Reyes wrote up an article—exploring four behaviors from the .NET MAUI Community Toolkit.
The .NET MAUI Community Toolkit encompasses a range of elements such as animations, converters and behaviors—all designed to simplify common developer tasks when building iOS, Android, macOS and WinUI applications using .NET MAUI. Behaviors enable the addition of specific functionalities to UI elements. These modular features enhance functionality toward better UX.
Leomaris showcases four wonderful behaviors from the .NET MAUI Community Toolkit—EmailValidator, Masked, IconTintColor and Animations. Starting from basic configuration, Leomaris walks through how developers can hook up the behaviors to UI elements, explore properties and see the resulting UI light up wonderful user experiences with little code—developer productivity for the win.
With .NET MAUI, developers can target mobile and desktop form factors from a single shared codebase. While the codebase is shared, user experiences should not be the same—.NET MAUI developers are encouraged to cater to mobile and desktop experiences based on the device form factors. Matt Goldman is no stranger to building first-class mobile/desktop experiences with .NET MAUI and wrote up an interesting article—responsive design with orientation changes in .NET MAUI.
A common UX paradigm for apps is to offer different layouts on mobile and desktop—a list of items with a secondary detail page on mobile and a two-pane list/detail layout for desktop. On tablets offering increased real estate, Matt wanted a responsive layout with portrait mode behaving like mobile, and landscape mode mimicking desktop UX. Things get a little challenging on iPads with support for multitasking using split view/slide-over—orientation of the device doesn’t necessarily reflect the orientation of the app.
Matt explored a few potential workarounds before settling on a reliable solution. The SizeChanged event is a dependable way of knowing page resizing events. Matt showcases how to leverage SizeChanged event handlers to programmatically trigger visual state changes, and update UI layout accordingly—lots of inspiration for .NET MAUI developers who want to carefully fine tune the UX across devices and orientation changes.
.NET MAUI is the evolution of modern .NET cross-platform development stack, allowing developers to reach mobile and desktop form factors from single shared codebase. The present reality for many apps, however, may be Xamarin or Xamarin.Forms. A migration strategy is needed to move things forward. Lance McCarthy has been busy trying to migrate a sample Telerik app and joined an aging developer to share experiences on the .NET Dev Show—moving CRM app code from Xamarin.Forms to .NET MAUI.
May 2024 is when official support runs out for Xamarin and Xamarin.Forms—now would be a great time to start the migration to .NET MAUI. The Telerik Art Gallery CRM app is a wonderful showcase app available in iOS/Android/Windows App Stores—written with Xamarin.Forms and source code up on GitHub. The move forward may be a great time to inspect the need for certain app features and plot migration of backend services with dependencies on older runtimes.
Thankfully, much of the C# and XAML code from Xamarin.Forms should move forward seamlessly into .NET MAUI, albeit with a few changes. Lance took the time to show off the tweaks toward maximum code reuse. The real benefits of moving to .NET MAUI are the truly shared single project, reusable assets, dependency injection and increased platform reach. Lance is scheduled for future episodes on the .NET Dev Show—should be a great series on migration tactics to move a real-world app from Xamarin to .NET MAUI.
That’s it for now.
We’ll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>The .NET MAUI Community Toolkit is a curated collection of reusable components thoughtfully developed by the community. It encompasses a range of elements such as animations, converters and behaviors, all designed to accelerate app development. What’s more, it ensures seamless compatibility across iOS, Android, macOS and WinUI, all thanks to the power of .NET MAUI.
In this article, we’ll dive into four fantastic behaviors from the .NET MAUI Community Toolkit that can supercharge your application. The best part? They’re ready to use! All you need is to understand how to implement them.
The behaviors we’ll explore are:
Each of these behaviors from the .NET MAUI Community Toolkit is designed to offer specific enhancements for your app.
But first, a brief pause: What exactly are behaviors?
Behaviors enable the addition of specific functionalities to view elements. These modular features not only enhance reusability but also streamline the unit testing process.
✍️ If you want to know more about behaviors, I invite you to check out the official documentation article.
To correctly implement the behaviors, ensure that the .NET MAUI Community Toolkit is properly configured in your app. Setting it up is straightforward, as outlined in the steps below:
UseMauiApp<App>()
, append:.UseMauiCommunityToolkit()
xmlns:toolkit="[http://schemas.microsoft.com/dotnet/2022/maui/toolkit](http://schemas.microsoft.com/dotnet/2022/maui/toolkit)"
This behavior detects whether the provided text is a valid email address using a regular expression. As a result, developers can easily provide visual feedback to users regarding the validity of their email. For instance, imagine an Entry where the font color turns red for an invalid email and green when it’s valid.
When paired with an InputView (like Entry or Editor), this behavior automatically sets the keyboard to Keyboard.Email, unless a different default keyboard has been specified.
We’ll begin with a hands-on code example.
We’re designing an Entry where the font size is set to 25 and the text is dark red when the email is invalid. Conversely, for a valid email, the font size will be 30 with green text.
We’ll define styles to encapsulate the desired visual attributes for each scenario.
➖ Invalid email:
<Style x:Key="InvalidEmailStyle" TargetType="Entry">
<Setter Property="FontSize" Value="25"/>
<Setter Property="TextColor" Value="DarkRed"/>
</Style>
➖ Valid email:
<Style x:Key="ValidaEmailStyle" TargetType="Entry">
<Setter Property="FontSize" Value="30"/>
<Setter Property="TextColor" Value="Green"/>
</Style>
EmailValidator boasts several properties, with some of the most notable ones listed below:
▪ InvalidStyle and ValidStyle – Receive a Style as value. These are the styles to be presented to the user when the email is invalid or valid, respectively.
▪ Flags – Receives ValidationFlags as value. This enum defines how validation is managed. The values of this enumeration are:
Now, let’s add the EmailValidationBehavior to our Entry, keeping in mind the properties we discussed earlier.
<Entry>
<Entry.Behaviors>
<toolkit:EmailValidationBehavior
InvalidStyle="{StaticResource InvalidEmailStyle}"
ValidStyle="{StaticResource ValidaEmailStyle}"
Flags="ValidateOnValueChanged" />
</Entry.Behaviors>
</Entry>
The outcome should resemble the following:
The Masked Behavior allows users to apply an input mask for specific data entry, ensuring consistency by only accepting values that fit the given mask. This is especially useful for standardized data formats, like credit card numbers, telephone numbers and more.
We’ll begin with a hands-on code example.
We’re setting up a mask for Dominican Republic phone numbers. Given a sample number like (800) 222-4434, the mask format will be: (XXX) XXX-XXXX.
There are two properties that will help you define your mask, which are the following:
▪ Mask – Receives a string as value. Specifies the mask pattern the input value should adhere to. Mandatory. There are two ways to set up this mask:
XXX XXX XXXX
.(XXX) XXX XXXX
. Here, the parentheses aren’t replaced, but instead are displayed as you type in the format. To utilize this feature effectively, you should also engage the UnmaskedCharacter property.▪ UnmaskedCharacter – Indicates the character within the Mask property that will be substituted with the user’s input. The character not specified in this property remains visible to the user. Referring to our earlier example, the value for this property will be X
, ensuring that parentheses are not replaced.
Now, let’s add the MaskedBehavior to our Entry, keeping in mind the properties we discussed earlier.
<Entry Keyboard="Numeric" Placeholder="(XXX) XXX XXXX">
<Entry.Behaviors>
<toolkit:MaskedBehavior Mask="(XXX) XXX XXXX" UnmaskedCharacter="X" />
</Entry.Behaviors>
</Entry>
✍️ I added the placeholder property to provide users with clearer guidance on the expected format.
The result should look like this:
This behavior enables image tinting. This proves invaluable when tailoring your apps for light and dark modes. Instead of needing separate icons for each mode, you can use a single icon and adjust its tint color based on your requirements.
We’ll begin with a hands-on code example.
We’ll apply a red tint to an icon. However, in another example, this icon will switch to orange when the device is set to dark mode and turn green in light mode.
This behavior has a singular property named TintColor, which determines the hue for the icon tint. For instance, to achieve a red-tinted icon, follow the steps below.
✍️ Keep in mind that the starting color of the icon is blue.
<Image Source="heart" HeightRequest="150" WidthRequest="150">
<Image.Behaviors>
<toolkit:IconTintColorBehavior TintColor="Red" />
</Image.Behaviors>
</Image>
Now, let’s play the appearance modes.
<Image Source="heart" HeightRequest="150" WidthRequest="150">
<Image.Behaviors>
<toolkit:IconTintColorBehavior TintColor="{AppThemeBinding Dark=Orange, Light=green}" />
</Image.Behaviors>
</Image>
✍️ Interested in mastering your user interface for different appearance modes? Dive into our article Managing Light and Dark Mode with .NET MAUI.
This is a behavior designed to animate any attached VisualElement seamlessly. While its default mode employs a TapGestureRecognizer to initiate the animation, this trigger activates upon detection of a user’s tap or click on the VisualElement, ensuring a responsive and dynamic interaction.
We’ll begin with a hands-on code example.
Imagine an image on the screen. Upon clicking or tapping it, the image undergoes a smooth fade effect.
Now, let’s add the AnimationBehavior to our Image:
<Image Source="dotnet_bot.png">
<Image.Behaviors>
<toolkit:AnimationBehavior>
<toolkit:AnimationBehavior.AnimationType>
<toolkit:FadeAnimation />
</toolkit:AnimationBehavior.AnimationType>
</toolkit:AnimationBehavior>
</Image.Behaviors>
</Image>
The result should look like this:
✍️ Curious about more animation types in .NET MAUI? Dive into our article Exploring Basic Animations in .NET MAUI.
And there you have it! With these straightforward steps, we’ve successfully implemented the behaviors discussed earlier.
I hope this list of helpful behaviors from .NET MAUI Community Toolkit was beneficial to you! I encourage you to implement them into your daily life and continue exploring others!
See you next time! ♀️
This article was based on the official documentation:
Use a component library in sync with .NET MAUI’s release cadence. Try Telerik UI for .NET MAUI for free.]]>
Displaying and editing rich text are often needed for end-user applications. No matter whether we are targeting Windows, macOS, iOS or Android, or whether we need just to send an email and format its content or to focus on editing and viewing documents, Telerik RichTextEditor is here to do the job. Available with R2 2023 (version 5.2.0) of Progress Telerik UI for .NET MAUI, this What-You-See-Is-What-You-Get (WYSIWYG) interface component comes with:
As with any of the other UI components from Telerik UI for .NET MAUI suite, adding Telerik RichTextEditor is simple and can be done in three steps:
UseTelerik()
method inside the Maui Program.cs file of your .NET MAUI project. This is needed for all Telerik UI for .NET MAUI components as UseTelerik()
registers all built-in or additionally created handlers to the Telerik components.XAML
<Grid>
<telerik:RadRichTextEditor x:Name="richTextEditor" AutomationId="richTextEditor"/>
</Grid>
xmlns:telerik="http://schemas.telerik.com/2022/xaml/maui"
C#
RadRichTextEditor richTextEditor = new RadRichTextEditor();
Telerik RichTextBox displays HTML content by offering a Rich API to retrieve the html from string or document. After that, all you should need to do is to set the Source
property.
Directly setting the Source to a string:
this.richTextEditor.Source = "<b>Hello World!</b>";
Using RichTextSource.FromString method to extract the HTML from a string:
var htmlSource = @"<h4>One of the Most Beautiful Islands on Earth - Tenerife</h4>
<p><strong>Tenerife</strong> is the largest and most populated island of the eight <a href='https://en.wikipedia.org/wiki/Canary_Islands' target='_blank'>Canary Islands</a>.</p>
<p style='color:#808080'>It is also the most populated island of <strong>Spain</strong>, with a land area of <i>2,034.38 square kilometers</i> and <i>904,713</i> inhabitants, 43% of the total population of the <strong>Canary Islands</strong>.</p>";
this.richTextEditor.Source = RichTextSource.FromString(htmlSource);
Using RichTextSource.FromStream method to read a stream (a very useful option when we need to load a document):
Func<CancellationToken, Task<Stream>> streamFunc = ct => Task.Run(() =>
{
Assembly assembly = typeof(GetHtml).Assembly;
string fileName = assembly.GetManifestResourceNames().FirstOrDefault(n => n.Contains(" PickYourHoliday.html"));
Stream stream = assembly.GetManifestResourceStream(fileName);
return stream;
});
this.richTextEditor.Source = RichTextSource.FromStream(streamFunc);
For the purpose of this post, I used the third approach and loaded a document containing images, links, tables and a lot of other complex HTML features as shown below:
We already loaded our full rich document, but what do we do in an editor if we don’t want to edit, right?
Telerik Editor offers rich functionality to do that, and all of that is exposed to user commands that we can bind to different UI depending on the needs of our application.
A table with all commands is below:
Commands | Description |
UndoCommand | Gets a command to undo the last changes in the editor. |
RedoCommand | Gets a command to redo the last changes in the editor. |
ToggleBoldCommand | Gets a command to toggle the bold text in the editor. |
ToggleItalicCommand | Gets a command to toggle the italic text in the editor. |
ToggleUnderlineCommand | Gets a command to toggle the underline text in the editor. |
ToggleStrikethroughCommand | Gets a command to toggle the strikethrough text in the editor. |
ToggleSubscriptCommand | Gets a command to toggle the subscript text in the editor. |
ToggleSuperscriptCommand | Gets a command to toggle the superscript text in the editor. |
ToggleBulletingCommand | Gets a command to toggle the bullets paragraph in the editor. |
ToggleNumberingCommand | Gets a command to toggle the numbered paragraph in the editor. |
ClearFormattingCommand | Gets a command to clear the formatting of the text in the editor. |
AlignLeftCommand | Gets a command to apply left text alignment in the editor. |
AlignRightCommand | Gets a command to apply right text alignment in the editor. |
AlignCenterCommand | Gets a command to apply center text alignment in the editor. |
AlignJustifyCommand | Gets a command to apply justified text alignment in the editor. |
IndentCommand | Gets a command to indent the text in the editor. |
OutdentCommand | Gets a command to outdent the text in the editor. |
ApplyHyperlinkCommand | Gets a command to apply a hyperlink in the editor. |
RemoveHyperlinkCommand | Gets a command to remove a hyperlink in the editor. |
OpenHyperlinkCommand | Gets a command to open a hyperlink in the editor. |
InsertImageCommand | Gets a command to insert an image in the editor. The command takes a single paramerer of type Telerik.Maui.Controls.RichTextEditor.RichTextImage. |
RemoveImageCommand | Gets a command to remove an image in the editor. |
SelectAllCommand | Gets a command to select all HTML in the editor. |
However, one of the most common scenarios is to edit the doc using the toolbar of the component—so this functionality comes built in.
The first time you visualize Telerik Editor, it appears with a toolbar containing buttons with all of the commands above.
By default, the Toolbar appears ready to be used with an adaptive look and feel. Still if you want to hide it or customize it, the first step is to set the AutoGenerateItems
property to False
.
Once the default toolbar is hidden, it is time to create a new one. The important part here is that you need to create an instance of RadRichTextEditorToolbar component outside the Telerik Editor but use the toolbar’s RichTextEditor
property to associate with the Editor component.
<telerik:RadRichTextEditorToolbar RichTextEditor="{x:Reference richTextEditor}" >
...
</telerik: RadRichTextEditorToolbar >
<telerik:RadRichTextEditor x:Name="richTextEditor" />
Then you can define which features to display. There are two ways to do that. You can use regular RadToolBarItems or use the predefined RichTextEditor toolbar items, which have assigned functionality. The code below illustrates the pre-built Editor toolbar items:
<telerik:RadRichTextEditorToolbar x:Name="richTextToolbar"
Grid.Row="{OnIdiom Desktop=0, Phone=1}"
ZIndex="10"
RichTextEditor="{x:Reference richTextEditor}"
AutoGenerateItems="False">
<telerik:RichTextEditorFontFamilyToolbarItem/>
<telerik:RichTextEditorFontSizeToolbarItem/>
<telerik:SeparatorToolbarItem/>
<telerik:RichTextEditorBoldToolbarItem/>
<telerik:RichTextEditorItalicToolbarItem/>
<telerik:RichTextEditorUnderlineToolbarItem/>
<telerik:SeparatorToolbarItem/>
<telerik:RichTextEditorAlignLeftToolbarItem/>
<telerik:RichTextEditorAlignCenterToolbarItem/>
<telerik:RichTextEditorAlignRightToolbarItem/>
<telerik:RichTextEditorAlignJustifyToolbarItem/>
<telerik:SeparatorToolbarItem/>
<telerik:RichTextEditorTextColorToolbarItem/>
<telerik:RichTextEditorHighlightTextColorToolbarItem/>
<telerik:SeparatorToolbarItem/>
<telerik:RichTextEditorAddOrEditHyperlinkToolbarItem />
<telerik:RichTextEditorRemoveHyperlinkToolbarItem />
<telerik:RichTextEditorAddOrEditImageToolbarItem />
<telerik:SeparatorToolbarItem/>
<telerik:RichTextEditorBulletingToolbarItem />
<telerik:RichTextEditorNumberingToolbarItem />
<telerik:SeparatorToolbarItem/>
<telerik:RichTextEditorOutdentToolbarItem/>
<telerik:RichTextEditorIndentToolbarItem/>
<telerik:SeparatorToolbarItem/>
<telerik:RichTextEditorTextFormattingToolbarItem/>
<telerik:SeparatorToolbarItem/>
<telerik:RichTextEditorClearFormattingToolbarItem/>
<telerik:SeparatorToolbarItem/>
<telerik:RichTextEditorStrikethroughToolbarItem/>
<telerik:RichTextEditorSuperscriptToolbarItem/>
<telerik:RichTextEditorSubscriptToolbarItem/>
<telerik:SeparatorToolbarItem/>
<telerik:RichTextEditorUndoToolbarItem/>
<telerik:RichTextEditorRedoToolbarItem/>
<telerik:RichTextEditorHyperlinkNavigationToolbarItem />
<telerik:RichTextEditorImageNavigationToolbarItem />
</telerik:RadRichTextEditorToolbar>
<telerik:RadRichTextEditor x:Name="richTextEditor" />
Now, let’s style them a little bit differently. As the RichTextEditor’s Toolbar is based on the RadToolbar control, all toolbar items in the RichTextEditor inherit from ButtonToolbarItem. All styling properties available for the ButtonToolbarItem are also applicable to Editor’s toolbar items.
For example, to change the background of the items defined above, we can define the following style:
<Style TargetType="telerik:ButtonToolbarItemView" x:Key="commonStyle">
<Setter Property="MinimumWidthRequest" Value="40"/>
<Setter Property="BackgroundColor" Value="#804BDE74"/>
</Style>
And set it to them like this:
<telerik:RichTextEditorFontFamilyToolbarItem Style="{StaticResource commonStyle}"/>
To read more details about Telerik ToolBar for .NET MAUI and see what else it can offer, read the blog about ToolBar.
Telerik RichTextEditor also offers an API to the .NET MAUI developer to manipulate the control:
GetSelectionAsync
method – Asynchronously returns a RichTextSelection
object which defines the current text selection inside the editor (returns null
if no text is selected). The RichTextSelection
object contains the Text
itself as well as the Start
and End
position of the text characters.GetHtmlAsync
method of RichTextEditor – You can get the content created and updated inside the editor HTML.IsReadOnly
property – Controls the read-only state.As we saw already, the Telerik ToolBar can be customized, and this is true for the RichTextEditor itself as well. You can take advantage of the following styling properties: BorderColor
, BorderThickness
, CornerThickness
and BackgroundColor
.
For example, let’s apply them for the example above:
<telerik:RadRichTextEditor x:Name="richTextEditor"
BorderThickness="2"
BorderColor="#808660C5"
CornerRadius="5" />
RadRichTextEditor is prepared to enable the .NET MAUI developers with flexibility to achieve more complex scenarios by handling the events.
The RichTextEditor component exposes the following events:
OpenHyperlinkError
– Raised when users try to open invalid URLs in the editorIsReadOnlyChanged
– Raised when the read-only mode of the RichTextEditor is switchedFontFamilyChanged
– Raised when the FontFamily
property of the RichTextEditor is modifiedFontSizeChanged
– Raised when the FontSize
property of the RichTextEditor is modifiedFontAttributesChanged
– Raised when the FontAttributes
, such as bold, italic, subscript or superscript, is modifiedTextDecorationsChanged
– Raised when the TextDecorations
, such as underline or strikethrough, is modifiedTextFormattingChanged
– Raised when the TextFormatting
, such as such as heading, paragraph or quotation, is modifiedHorizontalTextAlignmentChanged
– Raised when the HorizontalTextAlignment
, such as left, right, center or justify, is modifiedListTypeChanged
– Raised when the ListType
, such as numbered or bulleted list, is modifiedTextColorChanged
– Raised when the TextColor
property of the RichTextEditor is updatedHighlightTextColorChanged
– Raised when the HighlightTextColor
property of the RichTextEditor is updatedSelectionRangeChanged
– Raised when the SelectionRange
, which defines the start and end position of the currently selected inside the editor text, is updatedIsHyperlinkSelectedChanged
– Raised when a hyperlink inside the editor is selectedTelerik RichTextEditor for .NET MAUI shares the same API as Telerik RichTextEditor for Xamarin.Forms, so no big changes here. Still there two things to have in mind:
For more details, you can refer to the Telerik Migration from Xamarin article.
Full examples illustrating the power of the Telerik UI for .NET MAUI RichTextEditor can be found in the Telerik SDK and Telerik Controls Samples.
More details about the API and using the component can be found in Telerik documentation.
Telerik RichTextEditor is just one of more than 60 powerful and feature-rich components in the Telerik UI for .NET MAUI suite, built to help you develop outstanding cross-platform applications. Try it for free now, and if there is anything you need—do not hesitate to share your feedback and ideas with the Telerik team on Telerik Feedback Portal or Telerik Forums.
]]>A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
.NET developers are excited with the reality of .NET Multi-platform App UI (.NET MAUI)—the evolution of modern .NET cross-platform developer technology stack. With stable tooling and a rich ecosystem, .NET MAUI empowers developers to build native cross-platform apps for mobile/desktop from single shared codebase, while inviting web technologies in the mix.
While it may take a long flight to reach the sands of MAUI island, developer excitement around .NET MAUI is quite palpable with all the created content. Like the grains of sand, every piece of news/article/documentation/video/tutorial/livestream contributes towards developer experiences in .NET MAUI and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here’s what is noteworthy for the week of February 12, 2024:
With .NET MAUI, developers can target mobile and desktop form factors from a single shared codebase. The reality for serious .NET MAUI app development, however, means catering to different platform experiences and building complex yet performant UI that renders consistently across devices.
It would be nice if developers could get more productive building .NET MAUI app functionality without having to reinvent the wheel for UI complexity—and representing hierarchical data is particularly tricky across platforms. The latest release of Telerik UI for .NET MAUI includes the much-desired TreeView component, and Viktoria Grozdancheva wrote up an article—expanding the .NET MAUI paradise with the Telerik TreeView UI.
Progress Telerik UI for .NET MAUI can help .NET MAUI developers be more productive—professionally engineered UI components shine with consistent rendering across platforms, fine-tuned performance and dependability with documentation/support.
Viktoria invites developers to explore the bravest hierarchical data visualization needs—the Telerik TreeView UI component is easy to bring into any .NET MAUI app, and works seamlessly across platforms. The Telerik TreeView UI is feature-rich by design—developers can expect data binding, UI virtualization, load on demand, expanding/collapsing nodes, single/multiple selection, checkbox support, commands, styling API, custom item templates and more, all built in.
Developers may be needing to build something similar to a mail client or the next file explorer, and Viktoria showcases the flexibility of the Telerik .NET MAUI TreeView UI and provides plenty of developer inspiration.
.NET MAUI is built to enable .NET developers to create cross-platform apps for Android, iOS, macOS and Windows, with deep native integrations, platform-native UI and hybrid experiences that extend the reach of Blazor/JS web UI technologies. With increased stability and a rich ecosystem, more developers are building cross-platform apps with .NET MAUI.
With increased usage comes obvious developer trends—and some choices/techniques in .NET MAUI development may be detrimental to app performance and code sanity. After covering tips and tricks in a recent .NET MAUI Community Standup, David Ortinau took time to write up key advice for developers—Dos and Don’ts with .NET MAUI.
.NET MAUI has an evolved and well-architected UI technology stack—much of this comes from lessons learned from the Xamarin ecosystem. David starts off with some obvious advice on how .NET MAUI apps bootstrap the first view and choices in navigation between views—AppShell is getting increasingly popular. There can be some “gotchas” in .NET MAUI development around nested tabs, referencing SVGs and unconstrained scrolling inside stacklayouts.
While custom renderers from Xamarin.Forms do work in .NET MAUI through Compatibility mode, David mentions a few caveats in how and when to customize UI across platforms—moving things to the new Handler architecture is obviously the right way forward. Twelve golden tips and tricks from folks who likely see the most .NET MAUI code—this is high value to developers.
While .NET MAUI provides flexibility for .NET developers wanting to build cross-platform native mobile/desktop apps, the large majority of .NET MAUI developers will likely end up using C#/XAML to define app UI. There is good news for developers wanting to polish up their UI building skills—say hello to January XAML Fest by Leomaris Reyes, a month-long celebration dedicated to all things XAML in .NET MAUI. The goal of the special series is to delve deep into the world of UI design by replicating key portions of UI from renowned apps, and the last article is up—recreate the Instagram suggestion card UI in .NET MAUI.
With January XAML Fest, Leomaris has rolled out a collection of articles—each tackling a different piece of UI, breaking down the XAML code, and providing developers with a clear, concise guide to crafting such UI themselves. The Instagram suggestion card UI is a sleek and functional interface element that is a staple in modern mobile app design.
Leomaris starts by breaking down the original Instagram card UI into blocks that can be recreated, complete with everything needed to display the suggestions—frame, profile with rounded images and action buttons. With concise XAML and explanations every step of the way, Leomaris slowly builds up the Instagram suggestion card UI one block at a time with well-aligned text, mock data, images and buttons. There is plenty of UI inspiration for .NET MAUI developers. January XAML Fest was a festival of code and design, where developers were invited to celebrate, learn and enhance UI skills—thanks for the great series, Leomaris.
Modern mobile apps do not live in silos—they are often partnered up with an API or a backend service for continuity of user experiences. During the development cycles, developers often encounter the issue of debugging the service locally on the machine, while the connecting mobile apps are running on emulators or physical devices—and machine boundaries can make communication difficult. The problem of accessing localhost from emulators/VMs/devices may soon be a thing of the past if the backend services are written on top of the ASP.NET stack, and James Montemagno wrote up an article—say hello to the game-changing Dev Tunnels.
Accessing services/web apps running as localhost on local machine has always been challenging from client apps running on emulators/VMs/devices. Dev Tunnels work by creating a unique URL that acts as a loopback to the local machine. This makes localhost accessible from the internet, thus making things reachable from emulators/VMs/devices or other machines.
Dev Tunnels are easy to set up through Visual Studio 2022 or CLI and support several authentication/authorization options. With accompanying videos and samples, James makes a strong case for using Dev Tunnels for .NET MAUI, web and cloud development—they can revolutionize development process efficiency, allowing for seamless testing, debugging and team collaboration.
.NET MAUI is the evolution of modern .NET cross-platform development stack, allowing developers to reach mobile and desktop form factors from single shared codebase. The present reality for many apps, however, may be Xamarin or Xamarin.Forms. A migration strategy is needed to move things forward. Lance McCarthy has been busy trying to migrate a sample Telerik app and joined an aging developer to share experiences on the .NET Dev Show—plotting migration of CRM app from Xamarin.Forms to .NET MAUI.
May 2024 is when official support runs out for Xamarin and Xamarin.Forms—now would be a great time to start the migration to .NET MAUI. The Telerik Art Gallery CRM app is a wonderful showcase app available in iOS/Android/Windows App Stores—written with Xamarin.Forms and source code up on GitHub. The reality for many migrations, unfortunately, is scope creep—it may be best to separate refactoring and feature fixes from the actual Xamarin to .NET MAUI upgrade.
The move forward may be a great time to inspect the need for certain legacy app features and plot migration of backend services with dependencies on older runtimes. Lance is scheduled for future episodes on the .NET Dev Show—should be a great series on migration tactics to move a real-world app from Xamarin to .NET MAUI.
That’s it for now.
We’ll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>2024 comes with a new Telerik and Kendo UI release and introduces an updated component release cadence. The current 2024 Q1 release is the first of the four planned releases throughout the year—one per quarter:
We moved from three to four releases per year to provide you with regular updates and more UI goodness. You may be wondering what will happen with our popular livestream and also … where is your webinar invite? We’ll still have these but on a phased schedule—in May and November. Patches and minor release updates will be issued in between on an as-needed basis.
Now, back to the release as it sure brings some nice additions. With 2024 Q1, Progress continues to empower developers to rapidly build engaging and highly functional digital experiences, while looking for trends that could reshape UI/UX development. In addition to inclusive, customizable and modern design, Telerik and Kendo UI products strive to make digital experiences more intuitive and responsive, including even human-like interactions.
What you’ve read are just the highlights. To see everything that is new in 2024 Q1, visit the What’s New in Telerik and Kendo UI Products page. For a deeper dive into each product, follow the links below.
It will help you to follow along if you download the latest bits. Existing Telerik or Kendo UI customers can do this right from Your Account page, or by updating your NuGet package reference to the latest version in your solutions. For our Angular, React and Vue libraries, you just need to install the latest npm packages.
If you’re new to Progress DevTools, our products come with a free 30-day trial so you can check them out for yourself.
Thanks for tuning in! Don’t forget: We love to hear your feedback!
]]>It has been a while since I dismantled my Christmas tree, but while doing so, I thought I ought to introduce you to a new species that hit the .NET MAUI market last summer. Ready to meet the .NET MAUI TreeView? Believe me, getting started with this tree view is a lot easier than taking down all the bits of the other tree’s decorations. Follow me.
What to expect from the TreeView from Progress Telerik UI for .NET MAUI? To put it in only two words—feature richness. Data binding, UI virtualization, load on demand, expanding/collapsing nodes, single/multiple selection, checkbox support, commands, styling API, custom item templates, etc.
What to expect from this blog post? To examine the .NET MAUI TreeView together but take it one step at a time. So, let’s pick a simple starting point and build up from there.
Assuming you already have a fresh .NET MAUI app and the Telerik.UI.for.Maui NuGet, bringing the TreeView component to this app is as brief as the following.
XAML:
<telerik:RadTreeView x:Name="treeView" />
C#:
RadTreeView treeView = new RadTreeView();
Easy-treesy! However, this is just the roots—no branches, no leaves.
And it is all because I promised to take things one step at a time. Let’s jump into the next section where we will slowly build up to achieve this result:
After all, this is one of the most common scenarios that we are used to in our everyday lives—your favorite mail client’s inbox, your favorite IDE’s project files or any other kind of a file explorer.
Just like I mentioned in the previous section, a tree without branches or leaves does not make much sense. So, I suggest we bring some data to ours and make it bloom.
The TreeView component in Telerik UI for .NET MAUI is specifically crafted to simplify data binding, whether the data structure is linear or a hierarchical one.
In addition, its UI Virtualization enables faster data visualization and effortless display of TreeView items while scrolling, regardless of the dataset size.
Looking at the above screenshot (our aim ), you may notice that I have chosen a hierarchical data structure. I also created two models describing the File and Folder nodes of our tree and the ViewModel that will contain the collection of folders. Check them out below.
File node model:
public class FileNode : NotifyPropertyChangedBase
{
private string name;
private string icon;
private string dateModified;
private string size;
public string Name
{
get => this.name;
set => this.UpdateValue(ref this.name, value);
}
public string Icon
{
get => this.icon;
set => this.UpdateValue(ref this.icon, value);
}
public string DateModified
{
get => this.dateModified;
set => this.UpdateValue(ref this.dateModified, value);
}
public string Size
{
get => this.size;
set => this.UpdateValue(ref this.size, value);
}
internal FolderNode Parent { get; set; }
}
Folder node model:
public class FolderNode : FileNode
{
public FolderNode()
{
this.Children = new ObservableCollection<FileNode>();
}
public ObservableCollection<FileNode> Children { get; private set; }
}
And the ViewModel:
public class MainPageViewModel : NotifyPropertyChangedBase
{
private ObservableCollection<FolderNode> folders;
public MainPageViewModel()
{
this.folders = this.GetFolderSource();
}
public ObservableCollection<FolderNode> Folders
{
get { return this.folders; }
set { this.UpdateValue(ref this.folders, value); }
}
private ObservableCollection<FolderNode> GetFolderSource()
{
FolderNode desktopFolder = new FolderNode() { Name = "Desktop", Icon = "\ue82a" };
desktopFolder.Children.Add(new FileNode() { Name = "Blog post draft.docx", Icon = "\ue898", DateModified = "Yesterday, 17:20", Size = "907 KB", Parent = desktopFolder });
desktopFolder.Children.Add(new FileNode() { Name = "Screenshot 20230805.png", Icon = "\ue852", DateModified = "Yesterday, 11:10", Size = "920 KB", Parent = desktopFolder });
desktopFolder.Children.Add(new FileNode() { Name = "Screenshot 20230806.png", Icon = "\ue852", DateModified = "Yesterday, 12:13", Size = "805 KB", Parent = desktopFolder });
desktopFolder.Children.Add(new FileNode() { Name = "Screenshot 20230807.png", Icon = "\ue852", DateModified = "Yesterday, 11:48", Size = "667 KB", Parent = desktopFolder });
desktopFolder.Children.Add(new FileNode() { Name = "Screen Recording 20230721.mov", Icon = "\ue874", DateModified = "Yesterday, 11:54", Size = "735 KB", Parent = desktopFolder });
FolderNode documentsFolder = new FolderNode() { Name = "Documents", Icon = "\ue82a" };
documentsFolder.Children.Add(new FileNode() { Name = "Document.docx", Icon = "\ue898", DateModified = "Yesterday, 12:02", Size = "722 KB", Parent = documentsFolder });
documentsFolder.Children.Add(new FileNode() { Name = "Book.xlsx", Icon = "\ue896", DateModified = "Today, 09:08", Size = "901 KB", Parent = documentsFolder });
documentsFolder.Children.Add(new FileNode() { Name = "Presentation.pptx", Icon = "\ue897", DateModified = "Today, 10:25", Size = "2.1 MB", Parent = documentsFolder });
documentsFolder.Children.Add(new FileNode() { Name = "Invoice_details.pdf", Icon = "\ue899", DateModified = "Yesterday, 18:40", Size = "310 KB", Parent = documentsFolder });
FolderNode resourcesFolder = new FolderNode() { Name = "Resources", Icon = "\ue82a" };
resourcesFolder.Children.Add(new FolderNode() { Name = "Fonts", Icon = "\ue82a", Parent = resourcesFolder });
FolderNode imagesFolder = new FolderNode() { Name = "Images", Icon = "\ue82a", Parent = resourcesFolder };
imagesFolder.Children.Add(new FileNode() { Name = "american_pancakes.png", Icon = "\ue852", DateModified = "Today, 09:01", Size = "20 KB", Parent = imagesFolder });
imagesFolder.Children.Add(new FileNode() { Name = "belgian_chocolate.png", Icon = "\ue852", DateModified = "Today, 09:02", Size = "20 bytes", Parent = imagesFolder });
imagesFolder.Children.Add(new FileNode() { Name = "blueberry_waffle.png", Icon = "\ue852", DateModified = "Today, 09:03", Size = "20 KB", Parent = imagesFolder });
imagesFolder.Children.Add(new FileNode() { Name = "tiramisu.png", Icon = "\ue852", DateModified = "Today, 09:04", Size = "20 KB", Parent = imagesFolder });
resourcesFolder.Children.Add(imagesFolder);
resourcesFolder.Children.Add(new FileNode() { Name = "appicon.svg", Icon = "\ue852", DateModified = "Yesterday, 10:32", Size = "513 bytes", Parent = resourcesFolder });
resourcesFolder.Children.Add(new FileNode() { Name = "logo.svg", Icon = "\ue852", DateModified = "Yesterday, 10:38", Size = "790 bytes", Parent = resourcesFolder });
FolderNode videosFolder = new FolderNode() { Name = "Videos", Icon = "\ue82a", Parent = resourcesFolder };
FolderNode mauiFolder = new FolderNode() { Name = "MAUI", Icon = "\ue82a", Parent = videosFolder };
mauiFolder.Children.Add(new FileNode() { Name = "Getting Started with MAUI.mov", Icon = "\ue874", DateModified = "31 March 2023, 15:04", Size = "324 MB", Parent = mauiFolder });
mauiFolder.Children.Add(new FileNode() { Name = "MAUI Webinar.mov", Icon = "\ue874", DateModified = "20 October 2022, 16:20", Size = "737 MB", Parent = mauiFolder });
mauiFolder.Children.Add(new FileNode() { Name = "Building a Newsletter App.mov", Icon = "\ue874", DateModified = "6 September 2022, 14:34", Size = "922 MB", Parent = mauiFolder });
videosFolder.Children.Add(mauiFolder);
FolderNode recordingsFolder = new FolderNode() { Name = "Recordings", Icon = "\ue82a", Parent = videosFolder };
recordingsFolder.Children.Add(new FileNode() { Name = "Screen Recording 20220721.mov", Icon = "\ue874", DateModified = "21 July 2022, 17:20", Size = "24,8 MB", Parent = recordingsFolder });
recordingsFolder.Children.Add(new FileNode() { Name = "Screen Recording 20220807.mov", Icon = "\ue874", DateModified = "7 August 2022, 14:34", Size = "19,3 MB", Parent = recordingsFolder });
videosFolder.Children.Add(recordingsFolder);
return new ObservableCollection<FolderNode>()
{
desktopFolder,
documentsFolder,
resourcesFolder,
videosFolder
};
}
}
Since I decided working with hierarchical data structure, there is one more thing I need to do. I need to apply a TreeViewDescriptor which simply provides a description of a hierarchical items source. In our case, I must define two descriptors for each data item type (file and folder) through the descriptor’s TargetType and specify the name of the property that will be displayed for the respective data item through the descriptor’s DisplayMemberPath.
What is left for our tree to grow some branches and leaves is to bind the Folders collection to it:
<telerik:RadTreeView x:Name="treeView" ItemsSource="{Binding Folders}">
<telerik:TreeViewDescriptor TargetType="{x:Type local:FolderNode}"
ItemsSourcePath="Children"
DisplayMemberPath="Name" />
<telerik:TreeViewDescriptor TargetType="{x:Type local:FileNode}"
DisplayMemberPath="Name" />
</telerik:RadTreeView>
Shall we check our progress?
I know, I know—this file explorer is not that awesome yet, but we will change that in the next section.
The .NET MAUI TreeView introduces a conditional styling feature that empowers users to apply distinct Styles to individual items based on specific conditions. This feature enables dynamic customization, allowing each item to have its own unique appearance based on predefined criteria. There is an awesome runnable example demonstrating the ItemStyleSelector of the TreeView in the SDK Browser Demo Application. Don’t miss out—make sure you check it.
The tree view component also exposes an ItemTemplate property with the help of which the appearance of each TreeView node can be personalized. This enables you to effortlessly insert specific icons within the nodes for example, enhancing the customization options for your specific scenario.
Let’s add one ItemTemplate for our files, and one for our folders.
<DataTemplate x:Key="FileTemplate">
<Grid ColumnDefinitions="Auto, *"
ColumnSpacing="8"
RowDefinitions="Auto, Auto"
Padding="0, 4">
<Label Grid.RowSpan="2"
Text="{Binding Icon}"
TextColor="{Binding Name, Converter={StaticResource FileTypeToIconColorConverter}}"
FontFamily="TelerikFontExamples"
FontSize="24"
VerticalOptions="Center"
VerticalTextAlignment="Center" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontSize="14"
VerticalOptions="Center" />
<HorizontalStackLayout Grid.Row="1"
Grid.Column="1"
VerticalOptions="Center"
Opacity="0.38">
<Label Text="{Binding DateModified}"
FontSize="12" />
<Label Text=""
FontFamily="TelerikFontExamples"
FontSize="12"
VerticalTextAlignment="Center" />
<Label Text="{Binding Size}"
FontSize="12" />
</HorizontalStackLayout>
</Grid>
</DataTemplate>
<DataTemplate x:Key="FolderTemplate">
<Grid ColumnDefinitions="Auto, *"
ColumnSpacing="4">
<Label Text="{Binding Icon}"
TextColor="{Binding TextColor, Source={x:RelativeSource AncestorType={x:Type telerik:TreeViewItemView}}}"
FontFamily="TelerikFontExamples"
FontSize="16"
VerticalTextAlignment="Center" />
<Label Grid.Column="1"
FontSize="16"
Text="{Binding Name}"
VerticalTextAlignment="Center"
Margin="{OnPlatform Default=0, MacCatalyst='0, 2, 0, 0', WinUI='0, -4, 0, 0'}" />
</Grid>
</DataTemplate>
Now, let’s use these in our TreeViewDescriptors:
<telerik:RadTreeView x:Name="treeView" ItemsSource="{Binding Folders}">
<telerik:TreeViewDescriptor TargetType="{x:Type local:FolderNode}"
ItemsSourcePath="Children"
ItemTemplate="{StaticResource FolderTemplate}" />
<telerik:TreeViewDescriptor TargetType="{x:Type local:FileNode}"
ItemTemplate="{StaticResource FileTemplate}" />
</telerik:RadTreeView>
I can guarantee you we achieved the result from the very first image in this blog post, but let me prove that to you by running our example on a mobile device as well (Android on the left, iOS on the right):
Lovely. Let’s level up a little more.
Based on your business scenario, single or multiple node selection can be allowed. Ours is simple and does not necessarily need to allow multiple selection, yet we can turn it on simply by setting the SelectionMode property of our TreeView to Multiple. Or we can also turn the selection off by setting the same property to None.
You can also display CheckBox elements and enable the selection of specific items from the ItemsSource. This is particularly cool, as the selected items are automatically added to the CheckedItems collection, granting the freedom to perform various actions, such as selecting or manipulating these items as desired.
Curious to try out something with me? I say we display these checkboxes and make new folder with the checked items on the click of a button. For the checkboxes to show, we need to set the CheckBoxMode property:
<telerik:RadTreeView x:Name="treeView"
ItemsSource="{Binding Folders}"
CheckBoxMode="Recursive">
<telerik:TreeViewDescriptor TargetType="{x:Type local:FolderNode}"
ItemsSourcePath="Children"
ItemTemplate="{StaticResource FolderTemplate}" />
<telerik:TreeViewDescriptor TargetType="{x:Type local:FileNode}"
ItemTemplate="{StaticResource FileTemplate}" />
</telerik:RadTreeView>
I set it to recursive as I want my parent folder node to propagate its checked state to the children file nodes. Next thing I want is a button that will be responsible for creating a folder with the checked items (be it files or entire folders).
<Grid>
<telerik:RadTreeView x:Name="treeView"
ItemsSource="{Binding Folders}"
CheckBoxMode="Recursive">
<telerik:TreeViewDescriptor TargetType="{x:Type local:FolderNode}"
ItemsSourcePath="Children"
ItemTemplate="{StaticResource FolderTemplate}" />
<telerik:TreeViewDescriptor TargetType="{x:Type local:FileNode}"
ItemTemplate="{StaticResource FileTemplate}" />
</telerik:RadTreeView>
<telerik:RadButton x:Name="createFolderWithSelectionBtn"
Style="{StaticResource FABStyle}"
Command="{Binding CreateFolderWithSelectionCommand}"
VerticalOptions="End"
HorizontalOptions="End"
Margin="0, 0, 16, 16" />
</Grid>
So far, so good, but we need a little more than that. Take a short breath and jump to next section, where we will make it all work.
As you may guess, we need to add some custom options for our button to create new folders with the checked tree view items. Gladly, we can do this by leveraging the commands support of the Telerik UI for .NET MAUI TreeView. The list of such includes expanding, collapsing, checking, unchecking and scrolling.
In our example, we will take advantage of the ItemCheckedCommand, ItemUncheckedCommand and, of course, a custom command for creating a folder with the nodes selection. Let’s upgrade the MainPageViewModel (the GetFoldersSource method will be skipped as there are no changes):
public class MainPageViewModel : NotifyPropertyChangedBase
{
private ObservableCollection<FolderNode> folders;
private FolderNode newFolderItem;
private int counter = 1;
private readonly Command createFolderWithSelectionCommand;
private readonly Command itemCheckedCommand;
private readonly Command itemUncheckedCommand;
public MainPageViewModel()
{
this.folders = this.GetFolderSource();
this.newFolderItem = new FolderNode() { Name = "New folder", Icon = "\ue829" };
this.createFolderWithSelectionCommand = new Command(this.CreateFolderWithSelection, this.CanCreateFolderWithSelection);
this.itemCheckedCommand = new Command(this.ItemChecked);
this.itemUncheckedCommand = new Command(this.ItemUnchecked);
}
public ObservableCollection<FolderNode> Folders
{
get { return this.folders; }
set { this.UpdateValue(ref this.folders, value); }
}
public ICommand CreateFolderWithSelectionCommand => this.createFolderWithSelectionCommand;
public ICommand ItemCheckedCommand => this.itemCheckedCommand;
public ICommand ItemUncheckedCommand => this.itemUncheckedCommand;
private ObservableCollection<FolderNode> GetFolderSource()
{
//Skipped this part as there is no change
}
private void CreateFolderWithSelection(object obj)
{
foreach (var item in this.newFolderItem.Children)
{
if (item is FolderNode folderNode)
{
if (folderNode.Parent != null)
{
int parentFolderIndex = this.Folders.IndexOf(folderNode.Parent);
this.Folders[parentFolderIndex]?.Children.Remove(folderNode);
}
else
{
this.Folders.Remove(folderNode);
}
}
else if (item is FileNode fileNode)
{
int parentFolderIndex = this.Folders.IndexOf(fileNode.Parent);
this.Folders[parentFolderIndex]?.Children.Remove(fileNode);
}
}
this.Folders.Insert(0, this.newFolderItem);
this.counter++;
this.newFolderItem = new FolderNode() { Name = $"New folder ({this.counter})", Icon = "\ue829" };
((Command)this.CreateFolderWithSelectionCommand).ChangeCanExecute();
}
private bool CanCreateFolderWithSelection(object arg)
{
return this.newFolderItem.Children.Count > 0;
}
private void ItemChecked(object obj)
{
if (obj is FolderNode folderNode)
{
newFolderItem.Children.Add(folderNode);
}
else if (obj is FileNode fildeNode)
{
newFolderItem.Children.Add(fildeNode);
}
((Command)this.CreateFolderWithSelectionCommand).ChangeCanExecute();
}
private void ItemUnchecked(object obj)
{
if (obj is FolderNode folderNode)
{
newFolderItem.Children.Remove(folderNode);
}
else if (obj is FileNode fileNode)
{
newFolderItem.Children.Remove(fileNode);
}
((Command)this.CreateFolderWithSelectionCommand).ChangeCanExecute();
}
}
Ready to see it in action? I am! And this time I am going to show you WinUI.
I am happy with our example and hope you are, too.
And since this is just one of the many possible scenarios that can be achieved with the help of the .NET MAUI TreeView, do not forget to pay proper attention to its online documentation, too.
If you reached this point of my blog, a huge thanks from me to you for reading it! And with that, I think it is your turn to take the wheel and take the TreeView to even higher levels.
Plug the .NET MAUI TreeView in your MAUI app and let us know what impression it made. And when you do, make sure to share your opinion and ideas either in the comment section below or by visiting the Telerik UI for .NET MAUI Feedback Portal.
If you are already actively developing outstanding MAUI applications with Telerik UI for MAUI, you already know how to get the latest bits. If by some chance you are a new explorer—you just need to sign up for our free 30-day trial, which gives you access to the components as well as our legendary technical support at zero cost. Just head to the Telerik UI for .NET MAUI overview page or click the button below to sign up for a trial today!
]]>A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
.NET developers are excited with the reality of .NET Multi-platform App UI (.NET MAUI)—the evolution of modern .NET cross-platform developer technology stack. With stable tooling and a rich ecosystem, .NET MAUI empowers developers to build native cross-platform apps for mobile/desktop from single shared codebase, while inviting web technologies in the mix.
While it may take a long flight to reach the sands of MAUI island, developer excitement around .NET MAUI is quite palpable with all the created content. Like the grains of sand, every piece of news/article/documentation/video/tutorial/livestream contributes towards developer experiences in .NET MAUI and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here’s what is noteworthy for the week of February 5, 2024:
.NET MAUI is built to enable .NET developers to create cross-platform apps for Android, iOS, macOS and Windows, with deep native integrations, platform-native UI and hybrid experiences that extend the reach of Blazor/JS web UI technologies. With increased stability and a rich ecosystem, there are lot more developers building cross-platform apps with .NET MAUI. Developer attention is precious, though, and knowledge is often best gained in bite-sized pieces. Maddy Montaquila has started a series of short videos for developers called .NET MAUI Minutes and the another wonderful video is up—introduction to VS Code for .NET MAUI development.
Visual Studio Code is the uber-popular lightweight code editor that works seamlessly across Windows/macOS/Linux. For many modern .NET developers, particularly those targeting iOS as a platform, Macs running macOS are common development machines. With Visual Studio for Mac retiring this year, for developers on macOS/Linux, VS Code represents the engineering consolidation of developer tooling—the lightweight editor brings a rich Extensions ecosystem. Developers building cross-platform apps with .NET MAUI are empowered with the new .NET MAUI VS Code Extension.
Maddy walked through how to get started with the Extension, along with needed dependencies. Developers are able to debug cross-platform/platform-specific code and run their .NET MAUI apps on any simulator or connected devices, based on target platforms. VS Code is now the preferred cross-platform editor for many .NET developers, and the new .NET MAUI VS Code Extension promises developer productivity.
While .NET MAUI provides flexibility for .NET developers wanting to build cross-platform native mobile/desktop apps, the large majority of .NET MAUI developers will likely end up using C#/XAML to define app UI. There is good news for developers wanting to polish up their UI building skills—say hello to January XAML Fest by Leomaris Reyes, a month-long celebration dedicated to all things XAML in .NET MAUI. The goal of the special series is to delve deep into the world of UI design by replicating key portions of UI from renowned apps, and the third article is up—recreate Microsoft’s LinkedIn Header UI in .NET MAUI.
With January XAML Fest, Leomaris has rolled out a collection of articles—each tackling a different piece of UI, breaking down the XAML code, and providing developers with a clear, concise guide to crafting such UI themselves. The LinkedIn header UI is a sleek and functional interface element that is a staple in modern mobile app design.
Leomaris starts by breaking down the original card UI into blocks that can be recreated, complete with everything needed to display the header—profile, icons, rounded images and action buttons. With concise XAML and explanations every step of the way, Leomaris slowly builds up the LinkedIn header UI one block at a time with well-aligned text, images and buttons—there is plenty of UI inspiration for .NET MAUI developers. January XAML Fest is a festival of code and design, where developers are invited to celebrate, learn and enhance UI skills.
Seeing is believing. Before choosing a technology stack, developers often want to see success stories and amazing apps being with a framework—wow moments create enticement and challenge further creativity. As the evolution of the .NET cross-platform technology of choice, .NET MAUI sports flexible UI stack, lots of performance tuning and easy integration with popular libraries. While consumer or enterprise apps have their needs, games can be very demanding on performance, graphics and flexibility with platforms/input devices. There is a wonderful new inspirational showcase app from Nick Kovalsky—say hello to open-sourced .NET MAUI space shooter game Etude.
The challenge was to create a simple yet heavily animated arcade cross-platform game using .NET MAUI C#/XAML with SkiaSharp graphics library. Nick delivers in style. The new space shooter game is written with .NET MAUI providing the runtime, DrawnUI NuGet package drawing virtual controls on a Skia canvas and free Lottie animations fulfilling the game’s animated content needs.
The game runs seamlessly on Android, Windows, iOS and macOS, all from a single shared code base. The power and versatility of .NET MAUI is evident in consistent UI/UX across platforms, and support for touch on mobile versus keyboard/mouse on desktop. With acceptable game FPS and a wonderfully responsive UI, space shooter proves what’s possible with .NET MAUI and paves the path for immersive games/app experiences—no dearth of developer inspiration.
Shipping apps to iOS/Android/Windows app stores is not for the fainthearted—with each platform having different gated rules, developers often feel the hassle of signing/distributing apps. With .NET continuing to be inviting to everyone without a barrier to entry, VS Code is the perfect lightweight code editor to get started with cross-platform app development with .NET MAUI.
VS Code is now the preferred cross-platform editor for many .NET MAUI developers, and there is additional help for developers trying to ship/publish .NET MAUI apps to app stores. Gerald Versluis produced the perfect walk-through video—publishing .NET MAUI apps to the Stores made easy from inside VS Code.
Publishing/archiving cross-platform .NET MAUI apps usually requires that developers remember platform-specific CLI commands—but now, this can be a thing of the past. The new .NET MAUI Archive/Publish tool is a nifty VS Code Extension that aims to ease developer pain in shipping cross-platform apps to various app stores. The extension packs a set of essential tools to streamline the process of packaging and publishing .NET MAUI projects—supported platform targets include Android, iOS and Windows. Developers can get help with managing Provisioning Profiles, Keystores, code signing keys, actual archival/publication and more.
Gerald takes time to showcase the developer experience in preparing to publish a sample app for Android/iOS. The .NET MAUI Publish tool has the promise to simplify shipping .NET MAUI apps from inside VS Code.
.NET MAUI is the evolution of modern .NET cross-platform development stack, allowing developers to reach mobile and desktop form factors from single shared codebase. The present reality for many apps, however, may be Xamarin or Xamarin.Forms—a migration strategy is needed to move things forward. Daniel Hindrikes has been busy trying to migrate one of his apps and produced a video documenting the lessons learned—experiences upgrading from Xamarin.Forms to .NET MAUI.
May 2024 is when official support stops for Xamarin and Xamarin.Forms—now would be a great time to start the migration to .NET MAUI. Daniel speaks with honesty—the plan was to create a new .NET MAUI project, move over reusable code, fix what is broken and re-publish the existing Xamarin.Forms app. The reality for many migrations, unfortunately, is scope creep—a lot of refactoring and feature fixes may become part of the Xamarin to .NET MAUI upgrade.
While Daniel may be running a little late with the .NET MAUI app rewrite, newer runtime/architecture have led to easier bootstrapping, cleaner code and an opportunity to rewrite TinyMVVM library. Overall though, Daniel recommends separating upgrades from improvements.
That’s it for now.
We’ll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>Welcome to the January XAML Fest! This article will guide you on how to create an Instagram suggestion card. If you’re unfamiliar, this refers to the card that appears in a horizontal list when Instagram suggests new friends.
We will cover various comprehensive topics, teaching you how to apply them in a simple way. This includes the use of borders, rounding an image, and more. So, let’s get started!
The January XAML Fest is a month-long initiative where we showcase various replications of iconic user interfaces. If you’re keen to learn more about this exciting journey, I encourage you to check out the article “Welcome to the January XAML Fest for .NET MAUI.”
For a comprehensive understanding, here’s an outline of the topics that will structure our article’s explanation:
Before we embark on the coding and design journey, it’s essential to make sure you’re fully prepared to make the most of this post. Here are some helpful tips to enhance your experience and increase your productivity as you recreate the Instagram suggestion card:
Visual reference of the original UI: To begin, we’ll display an image of the original UI, segmented into steps. Each one corresponds to a different aspect of the design we’ll be addressing.
In-depth design analysis: Each step will include an image highlighting the specific design element we’re concentrating on. This approach offers a clear and focused examination of each design component.
Guided coding sections: In every coding section, keep an eye out for a comment that says, “Insert the code being described in the following section here.” This comment serves as your prompt to insert the forthcoming code explanation right at that point, ensuring a smooth and organized coding experience.
With all these tools at your disposal, you’re now fully equipped to dive into the UI code. Get ready for an exciting journey that offers hands-on experience and in-depth knowledge of .NET MAUI, particularly focusing on XAML for the graphical interface. Let’s start this enjoyable adventure—happy coding!
Before beginning to code, spend some time understanding the scope and implications of your project. This initial stage involves breaking down the design into smaller, manageable parts, each referred to as a “step.” Each step must have an order number, description and unique color for easy identification. This not only aids the development process but also makes this guide easier to follow. Let 's get started!
Let’s start by developing the main code structure. This will contain the code for all steps outlined in this article. Consider it as crafting the skeleton of your card, serving as the foundation for our upcoming steps. Let’s get started!
Our goal is to transform a single card design into a horizontal list using a CollectionView. This will enable us to add cards to the CollectionView corresponding to the number of records in our data source.
<CollectionView HorizontalScrollBarVisibility="Never"
ItemsSource="{Binding suggestions}"
ItemsLayout="HorizontalList"
HorizontalOptions="Fill">
<CollectionView.ItemTemplate>
<DataTemplate>
<!-- Here goes the code explained in the next explanation -- >
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
For demonstration purposes, we’ll introduce some mock data. This way, you can see your list in action.
➖ Create your Model: Begin by creating the Suggestions.cs class, which will serve as your model.
public class Suggestions
{
public string Picture { get; set; }
public string Name { get; set; }
public string Handle { get; set; }
}
➖ Populating Mock Data: Start by creating the SuggestionViewModel class. Below, I’ve provided data for three cards, but feel free to add as many as you need for your example.
public class SuggestionViewModel
{
public ObservableCollection<Suggestions> suggestions { get; set; }
public SuggestionViewModel() {
suggestions = new ObservableCollection<Suggestions>
{
new Suggestions { Picture = "brillante", Name="Mujer Brillante RD", Handle="mujerbrillanterd"},
new Suggestions { Picture = "jose", Name="Jose Perez", Handle="joseperez"},
new Suggestions { Picture = "marie", Name="Marie White", Handle="mariawhite"}
};
}
}
To link this data to the XAML, we will use the default page named MainPage.xaml. We will adjust the associated code behind (MainPage.xaml.cs) and add the BindingContext as follows:
public MainPage()
{
InitializeComponent();
BindingContext = new SuggestionViewModel();
}
We almost have the main structure ready to develop step by step! We only need to add the main layout. We’ll use a VerticalStackLayout, which will be located within the CollectionView and will contain the code blocks from steps one and two.
<VerticalStackLayout Padding="5,10" WidthRequest="170">
<!-- Here goes the code explained in the next explanation -- >
</VerticalStackLayout>
✍️ For more information about layouts in .NET MAUI, I invite you to read the article “Exploring Layout Options in .NET MAUI.”
Our structure is now in place! Let’s start crafting the visual elements for each step.
In the previous session, you will see code that says “<!-- Here goes the code explained in the next explanation -->
.” You must add the code that you will learn to create exactly here.
This step serves as the main container. It requires only one element: a box with rounded borders that encompasses all of the card’s content. Let’s explore this process:
➖ Box with rounded borders: We will use the Border control to add it. One key property is StrokeShape, which allows us to specify a rectangle with rounded edges, having a roundness value of 10, as demonstrated below:
<Border BackgroundColor="{AppThemeBinding Light=White,Dark=#222327}"
HeightRequest="220"
StrokeShape="RoundRectangle 10">
<!-- Add a layout of the following step here -- >
</Border>
In the BackgroundColor property, I added the AppThemeBinding markup extension. This allows us to assign values based on the appearance mode active on the user’s device. In this case, the background color will be white in light mode and gray in dark mode.
✍️ This topic is very interesting. I invite you to explore more by reading the article “Handling Light and Dark Mode With .NET MAUI.”
Now, you’ll see how your result should appear after the first step. There are two screenshots provided to show the outcomes in both light and dark modes.
⚠ Remember that there are three cards because we initially added three records to the mock data above.
Since Border control only allows one element inside and it contains various information, let’s include everything inside a grid layout. I selected the grid because it offers greater flexibility in organizing the necessary elements.
<Grid RowDefinitions="Auto,Auto,Auto,Auto,Auto" RowSpacing="7" HorizontalOptions="Fill" VerticalOptions="Center" Padding="5,10">
<!-- Add the close icon code here -->
<!-- Add the rounded image here -->
<!-- Add the names & handle here -->
<!-- Add the follow button here -->
</Grid>
Now, we are going to add each one of the elements of the card. They are the following:
➖ Close icon: Let’s start by adding the Close icon (X) located in the upper right part.
<Image Grid.Row="0" HorizontalOptions="End" VerticalOptions="Start" Source="close" HeightRequest="11" WidthRequest="11" Margin="0,0,5,0"/>
<!-- Insert the code being described in the following section here -->
➖ Rounded image: In previous articles, I used the AvatarView from the .NET MAUI Community Toolkit to create a rounded image. Now, I’ll demonstrate an alternative method by showing you how to achieve the same effect manually using a Frame.
<Frame Grid.Row="0" IsClippedToBounds="True" CornerRadius="40" HeightRequest="80" WidthRequest="80" HasShadow="False" Padding="0">
<Image Source="{Binding Picture}" Aspect="AspectFill" />
</Frame>
<!-- Insert the code being described in the following section here -->
➖ Name & handle:
<Label Grid.Row="2" HorizontalTextAlignment="Center" Text="{Binding Name}" FontSize="14" FontAttributes="Bold"/>
<Label Grid.Row="3" HorizontalTextAlignment="Center" Text="{Binding Handle}" FontSize="14" TextColor="Silver"/>
<!-- Insert the code being described in the following section here -->
➖ Follow button:
<Button Grid.Row="4" CornerRadius="10" TextColor="White" HorizontalOptions="Fill" HeightRequest="10" Text="Seguir" BackgroundColor="DodgerBlue"/>
Our final part is now ready! Your result should look like the following image in both light and dark mode:
And our Instagram Suggestion Card is done!
Thanks for reading! See you next time!
]]>A particle of sand—tiny and innocuous. But put a lot of sand particles together and we have something big—a force to reckon with. It is the smallest grains of sand that often add up to form massive beaches, dunes and deserts.
.NET developers are excited with the reality of .NET Multi-platform App UI (.NET MAUI)—the evolution of modern .NET cross-platform developer technology stack. With stable tooling and a rich ecosystem, .NET MAUI empowers developers to build native cross-platform apps for mobile/desktop from single shared codebase, while inviting web technologies in the mix.
While it may take a long flight to reach the sands of MAUI island, developer excitement around .NET MAUI is quite palpable with all the created content. Like the grains of sand, every piece of news/article/documentation/video/tutorial/livestream contributes toward developer experiences in .NET MAUI and we grow a community/ecosystem willing to learn and help.
Sands of MAUI is a humble attempt to collect all the .NET MAUI awesomeness in one place. Here’s what is noteworthy for the week of January 29, 2024:
.NET MAUI is built to enable .NET developers to create cross-platform apps for Android, iOS, macOS and Windows, with deep native integrations, platform-native UI, and hybrid experiences that extend the reach of Blazor/JS web UI technologies. With increased stability and a rich ecosystem, there are lot more developers building cross-platform apps with .NET MAUI. Developer attention is precious, though, and knowledge is often best gained in bite-sized pieces. Maddy Montaquila has started a series of short videos for developers called .NET MAUI Minutes and the another wonderful video is up—reusable styles in .NET MAUI.
Modern mobile/desktop apps should sport delightful UX and that often starts with wonderful UI that entices more app usage. XAML styles provide a convenient way to make apps attractive and have a consistent UI across platforms—and there are multiple ways for .NET MAUI developers to reuse styles throughout the app.
Maddy starts off with a quick introduction to default styling mechanisms in .NET MAUI, followed by easy-to-follow examples of using implicit and explicit styles. Developers have flexibility in how to reuse styles across pages or override cascading options when needed—styles can have specific UI targets and keys for matching. Better still, XAML styles can be combined into classes and UI elements can inherit multiple styles—developer productivity for the win. With easy XAML markup and reusable styles built into .NET MAUI, there isn’t much excuse to not make gorgeous app UI—XAML styles can help make beautiful apps with consistent UI across platforms.
While .NET MAUI provides flexibility for .NET developers wanting to build cross-platform native mobile/desktop apps, the large majority of .NET MAUI developers will likely end up using C#/XAML to define app UI. There is good news for developers wanting to polish up their UI building skills—say hello to January XAML Fest by Leomaris Reyes, a month-long celebration dedicated to all things XAML in .NET MAUI. The goal of the special series is to delve deep into the world of UI design by replicating key portions of UI from renowned apps, and the second article is up—recreate Twitter/X Card UI in .NET MAUI.
With January XAML Fest, Leomaris plans to roll out a collection of articles—each tackling a different piece of UI, breaking down the XAML code, and providing developers with a clear, concise guide to crafting such UI themselves. The Twitter/X Card UI is a sleek and functional interface element that is a staple in modern app design.
Leomaris starts by breaking down the original UI into blocks that can be recreated, complete with everything needed to display a tweet. With concise XAML and explanations every step of the way, Leomaris slowly builds up the Twitter/X UI one block at a time with well-aligned text, images and buttons—there is plenty of UI inspiration for .NET MAUI developers. January XAML Fest is a festival of code and design, where developers are invited to celebrate, learn and enhance UI skills.
Recording user screen from within an app—this might be a niche feature, but could be helpful for modern mobile/desktop apps. To report bugs, for example, users could simply record themselves using the app and send along the video. Screen recording from within the app is about to become trivial for .NET MAUI developers, thanks to Gerald Versluis and the preview of Plugin.Maui.ScreenRecording. To drive home the point, Gerald also produced a video—easily add screen recording to .NET MAUI apps.
Plugins are a great way to expose niche native platform functionality inside cross-platform .NET MAUI apps. To that end, there is quite a bit of help for developers from the .NET MAUI Plugin template repository. Gerald starts off by introducing Plugin.Maui.ScreenRecording, followed by installation of the NuGet package in a sample .NET MAUI project. With a quick extension method, Plugin.Maui.ScreenRecording can be configured to work for .NET MAUI apps. Platform reach includes iOS, macOS and Android.
For .NET MAUI apps wanting to use Plugin.Maui.ScreenRecording, permissions to save screen recording clips to the device media library has to be set up for iOS/macOS/Android—everything is well documented. Usage is rather easy with well-defined APIs to check device capability and start/stop recording. Gerald showcases usage with easy-to-follow sample on Android.
Developers love to hack something together—there is an inner nerdiness in pure creativity through code. While we can shut out the world and hack on our own, it is a different level of fun doing it with fellow developers. Throw in some coffee, learning from the community and experts at hand—you get a recipe for a fun day.
That’s exactly what the folks at SSW / SSW TV have planned for .NET MAUI developers—say hello to MAUI Hack Day, happening in person and online on Saturday, February 3, 2024.
MAUI Hack Days are community run events catering to .NET MAUI developers—for folks just diving into the world of .NET MAUI and seasoned developers alike. Hosted by Matt Goldman and Adam Cogan, MAUI Hack Day brings together experts from all around the world for a day of energized learning and churning out some code. MAUI Hack Day is a must-attend for all .NET MAUI enthusiasts—the perfect opportunity to skill up in down under, particularly Sydney, Melbourne, or Brisbane or entirely online.
.NET MAUI is the evolution of modern .NET cross-platform development stack, allowing developers to reach mobile and desktop form factors from a single shared codebase. While .NET MAUI is clearly the way forward, Xamarin is still the reality for many developers and enterprise apps.
With an end date in sight, many are plotting or in the middle of migration to .NET MAUI. There are some important dates and framework/tooling updates for folks in the Xamarin world though, and Leomaris Reyes wrote up the perfect summary—timeline of important events in the Xamarin ecosystem.
Inspired by details from David Ortinau, Leomaris plotted out important dates/events for developers dealing with Xamarin apps—the most important date is May 1, 2024, when official support for all Xamarin SDKs, including Xamarin.Forms, will end. Since Xamarin cross-platform apps have dependencies on underlying native platforms, there is marked shelf life for iOS/Android apps written with Xamarin SDKs—April 2025 for Apple store apps using XCode 15, and August 2025 for Google Play apps targeting API 34.
With .NET 8 paving the way for stable framework, tooling and performance updates, .NET MAUI will also stop support for .NET 7 in May 2024. Along the way, there are tooling updates for Xamarin/.NET MAUI developers as well—while Visual Studio for Mac retires in 2024, Visual Studio Code is rapidly building up features, while Visual Studio continues to be the gold standard for IDEs on Windows. Thanks, Leomaris, for recapping crucial dates/announcements—much appreciated by Xamarin and .NET MAUI developers.
That’s it for now.
We’ll see you next week with more awesome content relevant to .NET MAUI.
Cheers, developers!
]]>