Problem with custom control

Asked

Viewed 64 times

2

I created a custom search bar with an entry. I need to get the text of this entry to be a search parameter.

So I created a custom property that uses the Text property from entry. But this custom property does not take the custom search bar text.

What am I doing wrong? Below I leave the codes of the custom control.

Event code click custom search bar search button.

    private async void SbcPesquisar_OnClicked(object sender, EventArgs e)
        {            
            string busca = SbcPesquisar.TextSearch;
            List<Promocao> Promocoes = await PromocaoService.GetListaPromocoes(busca);
            LstPromocoes.ItemsSource = Promocoes;
        }

Code Bihind of Control

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace MeDeiBem.Controls
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class SearchBarCustom : ContentView
    {
        public event EventHandler ClickScope;
        public SearchBarCustom ()
        {
            InitializeComponent ();
        }
        public static readonly BindableProperty TextSearchProperty = 
            BindableProperty.Create(
                propertyName: "TextSearch",
                returnType: typeof(string),
                declaringType: typeof(SearchBarCustom),
                defaultValue: "",
                defaultBindingMode: BindingMode.TwoWay,
                propertyChanged: TextSearchPropertyChanged
            );

        public string TextSearch
        {
            get { return (string)GetValue(TextSearchProperty); }
            set { SetValue(TextSearchProperty, value); }
        }
        private static void TextSearchPropertyChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var searchBarCustom = (SearchBarCustom)bindable;
            searchBarCustom.textSearch.Text = (string)newValue;
        }
        private void On_clickScope(object sender, EventArgs e)
        {
            if (ClickScope != null)
            {
                ClickScope(sender, e);
            }
        }
    }
}

XAML:

    <?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" 
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:MeDeiBem.FontsAwesome;assembly=MeDeiBem"
             x:Class="MeDeiBem.Controls.SearchBarCustom">
  <ContentView.Content>
        <Frame Margin="10, 0, 10, 0" Padding="2" BorderColor="#49c1ff" CornerRadius="5" BackgroundColor="Transparent" HeightRequest="60">
            <StackLayout Orientation="Horizontal" BackgroundColor="Transparent">
                <Entry x:Name="textSearch"
                       Placeholder="Digite o que procura"                       
                       PlaceholderColor="Black"
                       FontSize="Medium"                       
                       BackgroundColor="Transparent"
                       HorizontalOptions="FillAndExpand" 
                       />

                <Button Text="{x:Static local:Fontes.FASearch}" 
                        FontSize="30"                          
                        BorderWidth="0"
                        BackgroundColor="Transparent"
                        WidthRequest="60" 
                        HorizontalOptions="End" 
                        Clicked="On_clickScope" />
            </StackLayout>
        </Frame>
  </ContentView.Content>
</ContentView>

XAML code where I’m using the component:

<controls:SearchBarCustom x:Name="SbcPesquisar" ClickScope="SbcPesquisar_OnClicked" />
  • Hello, I put the code in the question. Thank you.

1 answer

1


What you missed was using the BindableProperty TextSearchProperty that you created in your component. It is already exposed to Bindings.

Then you must have a property in your ViewModel, as SearchText, for example, and use it with Binding in the component. So:

<controls:SearchBarCustom x:Name="SbcPesquisar" 
                          TextSearch="{Binding SearchText}"
                          ClickScope="SbcPesquisar_OnClicked" />

That’s because in your delegate propertyChanged defined in BindablePropertyyou did reflect the property change TextSearch in the component Entry internal, but when the change occurs in the Entry your property TextSearch is not being notified ''.

Edit:

Unused Bindings (as is the case with MVVM), exposing the property as bindable ends up becoming unnecessary, as it was precisely for this that it was designed. But with a few small adjustments it is possible to solve the problem you are facing.

You will need to add a property x:Name in its component, define that it will be its own BindingContext and link the text of your Entry to the property you have exposed in the codebehind of the component. So:

<?xml version="1.0" encoding="UTF-8"?>
<ContentView ...
             x:Class="MeDeiBem.Controls.SearchBarCustom"
             x:Name="searchBarCustom">
    <ContentView.Content>
        <Frame Margin="10, 0, 10, 0" 
               BindingContext="{Reference searchBarCustom}"
               ...>
            <StackLayout Orientation="Horizontal" 
                         BackgroundColor="Transparent">
                <Entry x:Name="textSearch"
                       Text="{Binding TextSearch}"
                       Placeholder="Digite o que procura"                       
                       .../>

                <Button ... />
            </StackLayout>
        </Frame>
  </ContentView.Content>
</ContentView>

* Where the "..." is for you to keep your code the way it is today

This small adjustment will make changes to the Entry reflect on the property TextSearch and vice versa. You can now remove the implementation of propertyChanged: TextSearchPropertyChanged that you used in the BindableProperty.

By doing so you will be able to retrieve the content from the property as you were trying:

private async void SbcPesquisar_OnClicked(object sender, EventArgs e)
{            
    string busca = SbcPesquisar.TextSearch;
    List<Promocao> Promocoes = await PromocaoService.GetListaPromocoes(busca);
    LstPromocoes.ItemsSource = Promocoes;
}

I hope this helps.

  • Hello Diego. The problem is that I’m not using MVVM, so I don’t have a viewmodel.

  • 1

    Can you explain why it doesn’t make sense? I plan to use MVVM in my future projects. I stayed a little away from Xamarin and I’m still a little lost. But I want to better understand how MVVM works when you have more time.

  • @Marcosaurelio edited the answer. So it will work for you. This way I proposed in the end will be unnecessary to have the implementation of TextSearchPropertyChanged, can rule it out.

  • Diego, I did as Cvoce said, but in the XAML of the Reference error: The property searchBarCustom was not found in the Reference Extension type. The code is exactly as Voce did, I gave a name to my searchBarCustom component, put inside the tag Contentview.Bindingcontext.

  • It was my fault, I wrote in my head. The Referece it is not to be used as I had done. I have corrected. Try now

  • Diego worked. I had to thank you. Thank you.

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.