Обновление метки из свойства модели с вложенным представлением - PullRequest
1 голос
/ 06 февраля 2012

Прежде чем перейти к моему вопросу / проблеме, вот базовая структура моего приложения:

В моем файле MainWindow.xaml (в данном случае это основной вид) у меня есть ярлык (я понимаю, что должен измениться)это для TextBlock, но это отдельная проблема):

<Label Name="StatusLabel" Content="{Binding Path=Status}"/>

Это соответствующий ViewModel (MainWindowViewModel) содержит другой ViewModel (SiteListViewModel) и свойство Status:

public class MainWindowViewModel : ViewModelBase
{
    public SiteListViewModel SiteList { get; set; }
    public String Status
    {
        get { return SiteList.Status; }
    }
}

Как выМожно видеть, что свойство Status MainWindowViewModel возвращает свойство Status экземпляров SiteListViewModel, которое определяется следующим образом:

public class SiteListViewModel : ViewModelBase
{
    private string status;
    public String Status 
    {
        get { return this.status; }
        set
        {
            this.status = value;
            base.OnPropertyChanged("Status");
        }
    }
}

Свойство Status SiteListViewModel обновляется в различных местах во время асинхронных процессов, чтобы держать пользователя в курсе того, что происходитна.Это делается с помощью простых вызовов присваивания, таких как:

Status = String.Format(Properties.Resources.SiteListViewModel_Status_LoadingJobs, count + 1, totalSites);

Еще одно важное замечание: MainWindowViewModel и SiteListViewModel наследуются от ViewModelBase, который реализует INotifyPropertyChanged.

Теперь для актуального вопроса / проблемы:

Метка не обновляется.

Однако, если я изменю привязку в представлении на это:

<Label Name="StatusLabel" Content="{Binding Path=SiteList.Status}"/>

Работает нормально.Который, кажется, указывает, что я что-то упускаю на уровне MainWindowViewModel.Я мог бы оставить все как есть, но это затрагивает структуру модели дочернего представления, что я не хочу делать.

Может кто-то указать на то, что я делаю неправильно?

Ответы [ 3 ]

3 голосов
/ 07 февраля 2012

Конечно, он не обновляется, система привязки прослушивает события изменения для свойства, к которому вы привязываете тип, которому принадлежит это свойство, вы вообще не запускаете никаких уведомлений.

Вы можете переслать уведомления вложенной виртуальной машины:

public MainWindowViewModel
{
    SiteList.PropertyChanged += (s,e)
        => if (e.PropertyName == "Status") OnPropertyChanged("Status");
}

Где OnPropertyChanged - метод повышения PropertyChanged; базовый класс вашей виртуальной машины должен иметь что-то подобное.

Я бы порекомендовал отбросить свойство, хотя оно является избыточным, поскольку вы можете связать напрямую, хотя SiteList (также это свойство должно запускать уведомления об изменениях в его установщике). Также вам нужно будет отсоединить обработчик от старого экземпляра и повторно присоединить его к новому экземпляру всякий раз, когда изменяется SiteList (это также можно сделать в установщике).

0 голосов
/ 07 февраля 2012

Потому что MainWindow s DataContext равно MainWindowViewModel.

Label будет затем "наследовать" то же самое DataContext, поэтому Label s DataContex t также MainWindowViewModel. Вот почему вы должны сделать SiteList.Status. (Потому что вы не повышаете PropertyChanged в MainWindowViewModel, а в SiteListViewModel.)

0 голосов
/ 07 февраля 2012

То, что что-то реализует INotifyPropertyChanged, не означает, что оно будет автоматически знать, когда изменятся свойства. Вам необходимо вызвать событие PropertyChanged в своем коде.

В вашем примере это можно сделать, зарегистрировавшись на SiteListViewMode.PropertyChanged и подняв уведомление PropertyChanged для Status при изменении статуса.

public class MainWindowViewModel : ViewModelBase
{
    public SiteListViewModel SiteList { get; set; }
    public String Status
    {
        get { return SiteList.Status; }
    }

    public MainWindowViewModel()
    {
        // Of course, verify property isn't null first. 
        // Also, it's probably best to attach this in the setter
        // so you can unhook the event from old items too
        SiteList.PropertyChanged += SiteList_PropertyChanged;
    }

    void SiteList_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "Status")
            RaisePropertyChanged("Status");
    }
}
...