CrazyPhrog
CrazyPhrog

Reputation: 29

Using SearchButtonPressed Event on SearchBar control in Xamarin

I'm trying to display the text of a SearchBar control when the user presses the search button, but it's not working.

I use the MVVM model and Behaviors for this one, and when I debug it I can see that the values are correct and it does activate the right event, still the UI does not change.

The XAML file:

   <SearchBar Placeholder="Enter value...">
        <SearchBar.Behaviors>
            <local:MainViewModel/>
        </SearchBar.Behaviors>
   </SearchBar>
   <Label Text="{Binding LabelTextPress}"/>

The view model cs file:

public class MainViewModel : Behavior<SearchBar>, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public string val = "";
    public string LabelTextPress => "You entered after press: " + val;

    public string SearchValuePress
    {
        get
        {
            return val;
        }
        set
        {
            val = value;
        }
    }

    protected override void OnAttachedTo(SearchBar searchBar)
    {
        searchBar.SearchButtonPressed += SearchButtonPress;
        base.OnAttachedTo(searchBar);
    }

    protected override void OnDetachingFrom(SearchBar searchBar)
    {
        searchBar.SearchButtonPressed -= SearchButtonPress;
        base.OnDetachingFrom(searchBar);
    }

    void SearchButtonPress(object sender, EventArgs e)
    {
        this.GetType().GetProperty("SearchValuePress").SetValue(this, ((SearchBar)sender).Text, null);
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SearchValuePress)));
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LabelTextPress)));
    }
}

As you can see, The label should present the value of the search bar when the user presses the search button, but it only shows: "You entered after press: " which is the initial value of that string.

Thanks!

Upvotes: 1

Views: 2761

Answers (1)

jgoldberger - MSFT
jgoldberger - MSFT

Reputation: 6098

There are a few issues here, first and most importantly LabelTextPress is not a property, and also how you are implementing INotifyPropertyChanged is not correct. And Behavior class already implements INotifyPropertyChanged so you do not need to implement it again anyway.

More importantly, why do you need a behavior here? There is a command you can use for SearchBar to handle the search event in the view model.

Try the following:

XAML:

<SearchBar x:Name="searchBar"
           Placeholder="Enter value..."
           SearchCommand="{Binding SearchButtonPressed}"
           SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}">
    </SearchBar>
    <Label Text="{Binding LabelTextPress}"/>    

Try the following for your MainViewModel:

public class MainViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public ICommand SearchButtonPressed { private set; get; }

    public MainViewModel()
    {
        SearchButtonPressed = new Command<string>(HandleSearchPressed);
    }

    private void HandleSearchPressed(string searchText)
    {
        LabelTextPress = searchText;
    }

    string _labelTextPress;
    public string LabelTextPress
    {
        get
        {
            return "You entered after press: " + _labelTextPress;
        }
        set
        {
            if (_labelTextPress != value)
            {
                _labelTextPress = value;
                OnPropertyChanged();
            }
        }
    }

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }


}

Update to address new question in comments about TextChanged:

    <SearchBar x:Name="searchBar"
           Placeholder="Enter value..."
           TextChanged="Handle_TextChanged"
           SearchCommand="{Binding SearchButtonPressed}"
           SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}">

And in the Code behind:

void Handle_TextChanged(object sender, TextChangedEventArgs args)
{
     var viewModel = BindingContext as MainViewModel;
     viewModel.LabelTextPress = args.NewTextValue;
}

Upvotes: 3

Related Questions