Пользовательский интерфейс x: bind не обновляется, когда PropertyChanged в UWP - PullRequest
1 голос
/ 25 марта 2019

Я использую x:Bind и INotifyPropertyChanged для обновления пользовательского интерфейса в приложении UWP. Но он ведет себя как привязка OneTime, хотя я установил OneWay.

Bindings.Update() работает, но я хочу знать, почему INotifyPropertyChanged терпит неудачу.

1011 * XAML *

<TextBlock Text="{x:Bind staffVM.Name, Mode=OneWay}"/>

Код-за:

private StaffViewModel staffVM;
private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // I want to change staffVM according to ListView's selection.
    staffVM = staffListView.SelectedItem as StaffViewModel;
    staffVM.Update(); // If change this to Bindings.Update(), It works.
}

ViewModel:

public class StaffViewModel: INotifyPropertyChanged
{
    private Character character;
    public string Name => character.name == string.Empty ? null : character.name;
    public void Update()
    {
        RaisePropertyChanged(string.Empty);
    }

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged([CallerMemberName]string propName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}

Ответы [ 2 ]

0 голосов
/ 25 марта 2019

Проблема здесь не в уровне класса StaffViewModel, а в уровне страницы. Когда вы делаете:

staffVM = staffListView.SelectedItem as StaffViewModel;

Пользовательский интерфейс не уведомляет о том, что поле staffVM изменилось. Таким образом, привязка все еще указывает на старый экземпляр StaffViewModel. Следовательно, когда вы делаете staffVM.Update(), он уведомляет об изменениях, но пользовательский интерфейс не прослушивает этот экземпляр - он все еще прослушивает уведомления о первом выбранном элементе. Bindings.Update() исправляет это, потому что он полностью переоценивает все привязки, поэтому он "получит" новое значение поля staffVM.

Решением будет реализация INotifyPropertyChanged в Page и инкапсуляция staffVM в свойстве, которое вызывает событие PropertyChanged.

В идеале я бы предложил создать модель «корневого» представления, которую вы зададите только один раз и которая не изменится, и которая будет содержать выбранный элемент в качестве его свойства. Таким образом, вам не нужно реализовывать INotifyPropertyChanged в Page, и его код будет проще. В результате у вас будет что-то вроде следующего в коде:

public RootViewModel VM {get;} = new RootViewModel();

И в XAML:

<TextBlock Text="{x:Bind VM.SelectedStaff.Name, Mode=OneWay}"/>
0 голосов
/ 25 марта 2019

Во-первых, вам нужно указать имя переменной, которую вы хотите обновить:

public void Update()
{
    RaisePropertyChanged(nameof(Name));
}

Документация и образец: https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.data.inotifypropertychanged.propertychanged

Во-вторых, по умолчанию x: Bind is OneTime Чтобы исправить это, добавьте Mode="OneWay"

Mode Задает режим привязки в виде одной из следующих строк: «OneTime», «OneWay» или «TwoWay». По умолчанию используется «OneTime». Обратите внимание, что это отличается от значения по умолчанию для {Binding}, который в большинстве случаев является «OneWay».

Пожалуйста, прочитайте документацию https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/x-bind-markup-extension

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...