Search code examples
c#xamlxamarinmauicustom-controls

Where to do Content View Bussiness Logic Operations


I'm working on a .net maui app and i need to get and set data in my custom control.

The goal is:

Operation Template

The page:

    <ContentPage
    x:Class="V7.UIS.MauiMobile.Views.AboutPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:controls="clr-namespace:V7.UIS.MauiMobile.Controls.Views"    
    xmlns:viewmodel="clr-namespace:V7.UIS.MauiMobile.ViewModels"
    Title="About"
    ios:Page.UseSafeArea="true"
    x:DataType="viewmodel:AboutViewModel"
    BackgroundColor="{StaticResource NormalBackgroundColor}">

    <VerticalStackLayout>

        <controls:ItemBarcodeSearchView />

        <Entry Text="Count" />
        <Button
            Grid.Row="1"
            Grid.Column="1"
            Command="{Binding AddCommand}"
            Text="Add" />
    </VerticalStackLayout>
</ContentPage>

Custom control xaml:

<?xml version="1.0" encoding="utf-8" ?>
<ContentView
    x:Class="V7.UIS.MauiMobile.Controls.Views.ItemBarcodeSearchView"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:dxe="clr-namespace:DevExpress.Maui.Editors;assembly=DevExpress.Maui.Editors"
    x:Name="BarcodeSearchView">
    <ContentView.ControlTemplate>
        <ControlTemplate>
            <VerticalStackLayout>
                <Grid
                    x:Name="ButtonGrid"
                    Margin="5"
                    IsVisible="{TemplateBinding IsVisibleButtonGrid}">
                    <Button Clicked="ShowView" Text="Enter Barcode" />
                </Grid>
                <Grid
                    x:Name="DetailGrid"
                    Padding="15"
                    ColumnDefinitions="*"
                    ColumnSpacing="20"
                    IsVisible="{TemplateBinding IsVisibleDetailGrid}"
                    RowDefinitions="Auto,Auto"
                    VerticalOptions="Center">
                    <dxe:TextEdit
                        Grid.Row="0"
                        Margin="0"
                        ClearIconCommand="{TemplateBinding ClearFieldsCommand}"
                        ClearIconVisibility="Always"
                        LabelText="Barcode"
                        Text="{TemplateBinding Barcode}" />
                    <dxe:TextEdit
                        Grid.Row="1"
                        Margin="0"
                        ClearIconVisibility="Never"
                        LabelText="Item"
                        Text="{TemplateBinding ItemDescription}" />                    
                    <Button
                        Grid.Row="6"
                        Margin="0,10,0,0"
                        Command="{Binding Source={x:Reference BarcodeSearchView}, Path=Search}"
                        Text="Search" />
                    <Button
                        Grid.Row="7"
                        Margin="0,10,0,0"
                        Clicked="SendBarcodeDetails"
                        Text="Ok" />
                </Grid>
            </VerticalStackLayout>
        </ControlTemplate>
    </ContentView.ControlTemplate>
</ContentView>

When i press search button i want to execute this command for set itemdescription. This is the bussiness logic of that content view and i dont want to repeat this code over and over again.:

private readonly HttpClient _client;

public blabla(IHttpClientFactory factory)
{
_client = factory?.CreateClient(AppConstants.ApiName);
}

GetBarcodeDetailQuery query = new()
{
    Barcode = barcode
};
await client.GetDataFromApi<GetBarcodeDetailQuery, GetBarcodeDetailViewModel>("Cards/ItemBarcode/GetBarcodeDetail", query, FindBarcodeCallBack);

Where should i place this operation and how? i cant figure it out for a week.

Custom control xaml.cs :

using CommunityToolkit.Mvvm.Input;
using V7.UIS.MauiMobile.Models;

namespace V7.UIS.MauiMobile.Controls.Views;

public partial class ItemBarcodeSearchView : ContentView
{
    public ItemBarcodeSearchView()
    {
        InitializeComponent();
        IsVisibleButtonGrid = "true";
        IsVisibleDetailGrid = "false";
    }

    public event EventHandler<ItemBarcodeDetail> BarcodeDetailsReady;

    public static readonly BindableProperty BarcodeProperty =
        BindableProperty.Create(nameof(Barcode), typeof(string), typeof(ItemBarcodeSearchView));
    public static readonly BindableProperty ItemDescriptionProperty =
        BindableProperty.Create(nameof(ItemDescription), typeof(string), typeof(ItemBarcodeSearchView));    
    public static readonly BindableProperty IsVisibleButtonGridProperty =
        BindableProperty.Create(nameof(IsVisibleButtonGrid), typeof(string), typeof(ItemBarcodeSearchView));
    public static readonly BindableProperty IsVisibleDetailGridProperty =
        BindableProperty.Create(nameof(IsVisibleDetailGrid), typeof(string), typeof(ItemBarcodeSearchView));
    public static readonly BindableProperty SearchProperty =
            BindableProperty.Create(nameof(Search), typeof(RelayCommand), typeof(ItemBarcodeSearchView));

    public RelayCommand Search
    {
        get => (RelayCommand)GetValue(SearchProperty);
        set => SetValue(SearchProperty, value);
    }
    public string IsVisibleButtonGrid
    {
        get => (string)GetValue(IsVisibleButtonGridProperty);
        set => SetValue(IsVisibleButtonGridProperty, value);
    }
    public string IsVisibleDetailGrid
    {
        get => (string)GetValue(IsVisibleDetailGridProperty);
        set => SetValue(IsVisibleDetailGridProperty, value);
    }
    public string Barcode
    {
        get => (string)GetValue(BarcodeProperty);
        set => SetValue(BarcodeProperty, value);
    }
    public string ItemDescription
    {
        get => (string)GetValue(ItemDescriptionProperty);
        set => SetValue(ItemDescriptionProperty, value);
    }
    
    [RelayCommand]
    public void ClearFields()
    {
        Barcode = string.Empty;
        ItemDescription = string.Empty;        
    }

    private void SendBarcodeDetails(object sender, EventArgs e)
    {
        ItemBarcodeDetail itemBarcodeDetail = new()
        {
            Barcode = Barcode,
            ItemDescription = ItemDescription            
        };
        BarcodeDetailsReady?.Invoke(sender, itemBarcodeDetail);
        IsVisibleButtonGrid = "true";
        IsVisibleDetailGrid = "false";
    }
    private void ShowView(object sender, EventArgs e)
    {
        IsVisibleButtonGrid = "false";
        IsVisibleDetailGrid = "true";
    }
}

Hope someone here can help me.


Solution

  • The ContentView class defines a Content property, of type View, which represents the content of the ContentView. This property is backed by a BindableProperty object, which means that it can be the target of data bindings, and styled.

    The ContentView class offers little functionality by itself but can be used to create a custom control. The process for creating a custom control is to:

    • Create a class that derives from the ContentView class.
    • Define any control properties or events in the code-behind file for the custom control.
    • Define the UI for the custom control.

    For more information, you can check official document: Create a custom control.

    Note:

    You can also check the sample here ContentView Demos which will help you understand how to create a custom control with ContentView. Although this sample is an app for Xamarin form, it also applies to MAUI.