Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lawrence_shaun_introducing_net_maui_build_and_deploy_crosspl.pdf
Скачиваний:
46
Добавлен:
26.06.2023
Размер:
5.15 Mб
Скачать

Chapter 6 Creating Our Own Layout

BoardLayout.xaml.cs

Now that you have created your XAML representation, you need to add in the code-behind, which will work with it. We are going to follow a slightly different approach for this and the next section; you have a lot of code

to add now so you will add it in stages and we will talk around what you are adding.

The initial code should look as follows:

namespace WidgetBoard.Layouts;

public partial class BoardLayout

{

public BoardLayout()

{

InitializeComponent();

}

}

Adding the LayoutManager Property

You want to allow the consumer of your BoardLayout control to be able to supply a LayoutManager that will control where the widgets are placed. For this, you need to add the following:

private ILayoutManager layoutManager;

public ILayoutManager LayoutManager

{

get => layoutManager; set

{

layoutManager = value;

172

Chapter 6 Creating Our Own Layout

layoutManager.Board = this;

}

}

The key detail of this implementation is how it assigns the Board property on the LayoutManager to your BoardLayout control. This is to allow the manager to interact with the layout.

One very important thing to consider is that when you create properties that can be set in XAML, their setters can be called before your control has its BindingContext property set. Therefore, you usually need to handle both scenarios when relying on both pieces of functionality. To give a concrete example of this, you have your LayoutManager property that you have added. It will allow you to set bindings on it also, but it won’t have a BindingContext passed down. For this, you need to override the

OnBindingContextChanged method in your BoardLayout class and assign the value to your LayoutManager.

protected override void OnBindingContextChanged()

{

base.OnBindingContextChanged();

layoutManager.BindingContext = this.BindingContext;

}

In the past, I have found when building controls in this way, even if you do not need to use this method for an actual implementation, it can be really handy to debug what is going on when things don’t behave as expected. For example, you can stick a breakpoint in to make sure that you are being assigned a BindingContext and that it is of the correct type.

Adding the ItemsSource Property

Your BoardLayout also needs to accept a collection of widgets that will ultimately be displayed on screen. For controls that support

173

Chapter 6 Creating Our Own Layout

displaying multiple items, the common name used for such a property is ItemsSource. So, add a property with that name. You will need to add the following to the top of the file:

using System.Collections;

This is to allow you to use the IEnumerable type.

public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(

nameof(ItemsSource),

typeof(IEnumerable),

typeof(BoardLayout));

public IEnumerable ItemsSource

{

get => (IEnumerable)GetValue(ItemsSourceProperty); set => SetValue(ItemsSourceProperty, value);

}

In the majority of scenarios, you bind an ObservableCollection to an ItemsSource property, which is of a different type to IEnumerable. By choosing to use IEnumerable, it allows the consumers of your layout to provide any type that supports holding multiple items. This means that you can supply an ObservableCollection or you can supply a List.

Finally, you need to add the using statement into your BoardLayout. xaml.cs file at the top.

using System.Collections;

Adding the ItemTemplateSelector Property

Now that you have a collection of items to display on screen, you need to know how to display them. It can be common to see controls that have an ItemsSource property also have an ItemTemplate or an

174

Chapter 6 Creating Our Own Layout

ItemTemplateSelector or even both properties. An ItemTemplate allows a developer to define how each item in the ItemsSource will be rendered on screen. The reason you aren’t using this approach is because you can only define one template for all items. You will be binding your widget view models to the ItemsSource property, which means you will have several different views that you will want to display. This is where the

ItemTemplateSelector property comes in.

public static readonly BindableProperty ItemTemplateSelectorProperty =

BindableProperty.Create(

nameof(ItemTemplateSelector),

typeof(DataTemplateSelector),

typeof(BoardLayout));

public DataTemplateSelector ItemTemplateSelector

{

get => (DataTemplateSelector)GetValue(ItemTemplateSelector Property);

set => SetValue(ItemTemplateSelectorProperty, value);

}

You make use of the DataTemplateSelector type for your property here. You will create an implementation a little later in this chapter but for now it allows you to override the OnSelectTemplate method and provide a suitable template for the item that is passed in.

Handling the ChildAdded Event

I discussed earlier how the BindableLayout feature allows you to populate a control with multiple views based on bindings. You need to hook into the ChildAdded event so that your LayoutManager implementation can determine where the new child should be positioned.

175