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

Chapter 6 Creating Our Own Layout

Accepting the Number of Rows and Columns for a Board

You need to add the ability to set the number of rows and columns to be displayed in your fixed layout board. For this, you are going to add two bindable properties to your FixedLayoutManager class.

Adding the NumberOfColumns Property

public static readonly BindableProperty NumberOfColumnsProperty =

BindableProperty.Create(

nameof(NumberOfColumns),

typeof(int),

typeof(FixedLayoutManager), defaultBindingMode: BindingMode.OneWay, propertyChanged: OnNumberOfColumnsChanged);

public int NumberOfColumns

{

get => (int)GetValue(NumberOfColumnsProperty); set => SetValue(NumberOfColumnsProperty, value);

}

static void OnNumberOfColumnsChanged(BindableObject bindable, object oldValue, object newValue)

{

var manager = (FixedLayoutManager)bindable;

manager.InitialiseGrid();

}

179

Chapter 6 Creating Our Own Layout

The key difference with this implementation over the previous bindable properties that you created is the use of the propertyChanged parameter. It allows you to define a method (see OnNumberOfColumnsChanged) that will be called whenever the property value changes.

The property changed method will only be called when the value changes. This means that it may not be called initially if the value does not change from the default value.

Adding the NumberOfRows Property

public static readonly BindableProperty NumberOfRowsProperty = BindableProperty.Create(

nameof(NumberOfRows),

typeof(int),

typeof(FixedLayoutManager), defaultBindingMode: BindingMode.OneWay, propertyChanged: OnNumberOfRowsChanged);

public int NumberOfRows

{

get => (int)GetValue(NumberOfRowsProperty); set => SetValue(NumberOfRowsProperty, value);

}

static void OnNumberOfRowsChanged(BindableObject bindable, object oldValue, object newValue)

{

var manager = (FixedLayoutManager)bindable;

manager.InitialiseGrid();

}

180

Chapter 6 Creating Our Own Layout

This is virtually identical to the NumberOfColumns property that you just added, except for the NumberOfRows value.

Providing Tap/Click Support Through

a Command

The next item on your list is to provide the ability to handle tap/click support. This is your first time providing command support; you used commands in your bindings, but that was on the source side rather than the target side like here.

First, you need to add the bindable property, which should start to feel rather familiar.

public static readonly BindableProperty PlaceholderTappedCommandProperty =

BindableProperty.Create(

nameof(PlaceholderTappedCommand),

typeof(ICommand),

typeof(FixedLayoutManager));

public ICommand PlaceholderTappedCommand

{

get => (ICommand)GetValue(PlaceholderTappedCommand Property);

set => SetValue(PlaceholderTappedCommandProperty, value);

}

Next, you need to add the code that will execute the command. You will be relying on the use of a TapGestureRecognizer by adding one to your Placeholder control inside your InitialiseGrid method that you will be adding in the next section. For now, you can add the method that will be used so that you can focus on how to execute the command. Let’s add the code and then look over the details.

181

Chapter 6 Creating Our Own Layout

private void TapGestureRecognizer_Tapped(object sender, EventArgs e)

{

if (sender is Placeholder placeholder)

{

if (PlaceholderTappedCommand?.CanExecute(placeholder. Position) == true)

{

PlaceholderTappedCommand.Execute(placeholder.

Position);

}

}

}

You can see from the implementation that there are three main parts to the command execution logic:

•\

First, you make sure that command has a value.

•\

Second, you check that you can execute the command.

 

If you recall back in Chapter 5 you provided a method

 

to prevent the command from executing if the user

 

hadn’t entered a BoardName.

•\

Finally, you execute the command and pass in the

 

command parameter. For this scenario, you will be

 

passing in the current position of the placeholder so

 

when a widget is added, it can be placed in the same

 

position.

Building the Board Layout

Now you can focus on laying out the underlying Grids so that they display as per the user’s entered values for rows and columns.

182

Chapter 6 Creating Our Own Layout

First, add in a property to store the current Board because you need to use it when building the layout. You also need to record whether you have built the layout to prevent any unnecessary updates rebuilding the user interface.

private BoardLayout board; private bool isInitialised;

public BoardLayout Board

{

get => board; set

{

board = value;

InitialiseGrid();

}

}

Your method to build the grid layout has several parts, so let’s add them as you go and discuss their value. You initially need to make sure that you have valid values for the Board, NumberOfRows and NumberOfColumns properties plus you haven’t already built the UI.

private void InitialiseGrid()

{

if (Board is null || NumberOfColumns == 0 || NumberOfRows == 0 || isInitialised == true)

{

return;

}

isInitialised = true;

}

183

Chapter 6 Creating Our Own Layout

The next step is to use the NumberOfColumns value and add them to your Board. Let’s add this to the end of the InitialiseGrid method.

for (int i = 0; i < NumberOfColumns; i++)

{

Board.AddColumn(new ColumnDefinition(new GridLength(1, GridUnitType.Star)));

}

The GridUnitType.Star value means that each column will have an even share of the width of the grid. So, if the Grid is 300 pixels wide and you have 3 columns, then each column has a resulting width of 100 pixels.

The next step is to use the NumberOfRows value and add them to your Board. Let’s add this to the end of the InitialiseGrid method.

for (int i = 0; i < NumberOfRows; i++)

{

Board.AddRow(new RowDefinition(new GridLength(1, GridUnitType.Star)));

}

The final step in your InitialiseGrid method is to populate each cell (row and column) combination with a Placeholder control.

for (int column = 0; column < NumberOfColumns; column++)

{

for (int row = 0; row < NumberOfRows; row++)

{

var placeholder = new Placeholder();

placeholder.Position = row * NumberOfColumns + column; var tapGestureRecognizer = new TapGestureRecognizer();

184