Свойство привязки данных Silverlight 3 не обновляется - PullRequest
4 голосов
/ 19 апреля 2010

У меня есть элемент управления Silverlight, в котором мой корневой объект ViewModel является источником данных. ViewModel предоставляет список карт, а также свойство SelectedCard, которое связано с раскрывающимся списком в верхней части представления. Затем у меня есть форма сортировки внизу, которая отображает свойства выбранной карты. Мой XAML выглядит как (сокращено для простоты):

<StackPanel Orientation="Vertical">
  <ComboBox DisplayMemberPath="Name"
            ItemsSource="{Binding Path=Cards}"
            SelectedItem="{Binding Path=SelectedCard, Mode=TwoWay}"
            />
  <TextBlock Text="{Binding Path=SelectedCard.Name}"
             />
  <ListBox DisplayMemberPath="Name"
           ItemsSource="{Binding Path=SelectedCard.PendingTransactions}"
           />
</StackPanel>

Я бы ожидал, что TextBlock и ListBox будут обновляться всякий раз, когда я выбираю новый элемент в ComboBox, но это не так. Я уверен, что это связано с тем фактом, что TextBlock и ListBox на самом деле привязаны к свойствам SelectedCard, поэтому он прослушивает уведомления об изменении свойств для свойств этого объекта. Но я бы подумал, что привязка данных будет достаточно умной, чтобы распознать, что родительский объект в выражении привязки изменился, и обновить всю привязку.

Следует отметить, что свойство PendingTransactions (привязанное к ListBox) загружается с отложенной загрузкой. Итак, когда я в первый раз выбираю элемент в ComboBox, я делаю асинхронный вызов и загружаю список и обновления пользовательского интерфейса для отображения информации, соответствующей выбранному элементу. Однако при повторном выборе элемента пользовательский интерфейс не меняется!

Например, если мой оригинальный список содержит три карты, я выбираю первую карту по умолчанию. Привязка данных пытается получить доступ к свойству PendingTransactions этого объекта Card и корректно обновляет ListBox. Если я выберу вторую карточку в списке, произойдет то же самое, и я получу список PendingTransactions для этой карточки. Но если я снова выберу первую карту, в моем интерфейсе ничего не изменится! Устанавливая точку останова, я могу подтвердить, что свойство SelectedCard обновляется правильно.

Как я могу заставить эту работу ???

Ответы [ 3 ]

0 голосов
/ 19 апреля 2010

Шаблон, который я недавно использовал, - это привязка контекста данных контейнера подробной информации к выбранному элементу списка. XAML в вашем случае становится:

<StackPanel Orientation="Vertical">
    <ComboBox x:Name="_lbxCards"       <-- new
              DisplayMemberPath="Name"
              ItemsSource="{Binding Path=Cards}"
              SelectedItem="{Binding Path=SelectedCard, Mode=TwoWay}"
              />
    <StackPanel DataContext={Binding ElementName=_lbxCards,Path=SelectedItem}> <-- new
        <TextBlock Text="{Binding Path=Name}"                                  <-- updated
                   />
        <ListBox DisplayMemberPath="Name"
                 ItemsSource="{Binding Path=PendingTransactions}"              <-- updated
                 />
    </StackPanel>                                                              <-- new
</StackPanel>
0 голосов
/ 19 апреля 2010

Оказывается, проблема не в пользовательском интерфейсе вообще. Класс PendingTransactions лениво загружает свои значения с помощью асинхронного вызова WCF на сервер. Асинхронный шаблон использует события для уведомления вызывающей стороны о завершении операции, чтобы данные могли быть проанализированы в классе. Поскольку каждая карта имеет свой собственный экземпляр класса PendingTransactions и мы использовали ServiceFactory для управления нашими прокси-серверами WCF, каждый экземпляр подключал свой обработчик событий к одному и тому же событию (в настоящее время мы используем одноэлементный подход для повышения производительности - пока) , Таким образом, каждый экземпляр получал событие каждый раз, когда любой из экземпляров запускал асинхронную операцию.

Это означает, что привязка данных работала правильно. Коллекции PendingTransactions перезаписывались каждый раз при просмотре новой Карты. Таким образом, оказалось, что выбор предыдущей карты ничего не делал, когда, на самом деле, он выбирал правильный объект для привязки, это были данные, которые были испорчены и создавали впечатление, что ничего не меняется.

Спасибо за совет и руководство!

0 голосов
/ 19 апреля 2010

Если вы используете Silverlight 3, вам нужно использовать INotifyPropertyChanged.

Пример:

public class CardViewModel : INotifyPropertyChanged
{
 public event PropertyChangedEventHandler PropertyChanged;
 public ObservableCollection<Card> Cards { get; set; }
 private Card _selectedCard;
 public SelectedCard
 {
  get
  {
   return _selectedCard;
  }
  set
  {
   if (value != _selectedCard)
   {
    _selectedCard = value;
    NotifyPropertyChanged("SelectedCard");
   }
  }
 }
 public CardViewModel()
 {
  Cards = new ObservableCollection<Card>();
  //Populate Cards collection with objects
 }
 public void NotifyPropertyChanged(string item)
 {
  if (PropertyChanged!=null)
  {
   PropertyChanged(this, new PropertyChangedEventArgs(item));
  }
 }
}

Все, что вам нужно сделать, это установить этот класс для ваших представлений DataContext и всебудь счастлив.

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