Я пытаюсь отобразить текст элемента управления SearchBar, когда пользователь нажимает кнопку поиска, но он не работает.

Я использую модель MVVM и Behaviors для этого, и когда я отлаживаю его, я вижу, что значения верны, и оно активирует правильное событие, но пользовательский интерфейс не меняется.

Файл XAML:

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

Файл cs модели представления:

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)));
    }
}

Как видите, метка должна представлять значение строки поиска, когда пользователь нажимает кнопку поиска, но она показывает только: «Вы ввели после нажатия:», что является начальным значением этой строки.

Благодарность!

1
CrazyPhrog 14 Окт 2019 в 22:24

1 ответ

Лучший ответ

Здесь есть несколько проблем, во-первых, и самое главное, LabelTextPress не является свойством, а также неверно то, как вы реализуете INotifyPropertyChanged. И класс Behavior уже реализует INotifyPropertyChanged, поэтому вам все равно не нужно реализовывать его снова.

Что еще более важно, зачем вам здесь поведение? Существует команда, которую вы можете использовать для SearchBar для обработки события поиска в модели представления.

Попробуйте следующее:

XAML:

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

Попробуйте следующее для своего 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));
    }


}

Обновление, чтобы ответить на новый вопрос в комментариях о TextChanged:

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

И в Кодексе:

void Handle_TextChanged(object sender, TextChangedEventArgs args)
{
     var viewModel = BindingContext as MainViewModel;
     viewModel.LabelTextPress = args.NewTextValue;
}
3
jgoldberger - MSFT 17 Окт 2019 в 20:33