#c# #wpf
#c# #wpf
Вопрос:
Это моя структура данных:
public class Movie : IMovie
{
public string Title { get; set; }
public string Description { get; set; }
public List<IActor> Actors { get; set; }
}
public class Actor : IActor
{
string FirstName { get; set; }
string LastName { get; set; }
}
И это моя ViewModel:
public class MovieViewModel : BaseViewModel
{
public ObservableCollection<IMovie> Movies { get; set; } = new ObservableCollection<IMovie>();
public MovieViewModel()
{
foreach (var movie in blc.GetAllMovies())
Movies.Add(movie);
}
}
В моем MainWindow
я добавляю dataContext
этим:
this.DataContext = new MovieViewModel();
У меня есть 2 списка. Когда я выбираю фильм в первом списке, я хочу отобразить всех действующих лиц во втором списке.
Мне удалось отобразить фильмы. По какой-то причине актеры не отображаются при нажатии на какой-либо фильм.
<ListBox x:Name="moviesListBox" ItemsSource="{Binding Movies}" SelectedItem="{Binding SelectedMovie, Mode=TwoWay}" />
<ListBox x:Name="actorsListBox" ItemsSource="{Binding SelectedMovie.Actors}" SelectedItem="{Binding SelectedActor, Mode=TwoWay}" />
Что здесь не так?
Комментарии:
1. Как
SelectedMovie.Cast
определяется?2. @LewsTherin извините, там должно быть
Actors
. Это опечатка, когда я копировал это вso
.3. Совершенно не уверен, но просто по сходству с WinForms, доступен ли этот
SelectedValue = {}
атрибут? Если да, может быть, стоит попробовать?4. Является
SelectedMovie
свойством класса MovieViewModel и выдает ли оно уведомление об изменении свойства?5. Можете ли вы подтвердить, что список действующих лиц заполнен? Ваш код может быть в порядке, но без данных! Также у вас есть datatemplate для актеров? Зачем вам нужны имена в ваших списках?
Ответ №1:
Вы не показали, где / как определяется SelectedMovie (как он существует в своей viewmodel), но
-
viewmodel, в котором содержится SelectedMovie (предположительно, DataContext формы / страницы, содержащей элементы управления ListBox), должен реализовывать интерфейс INotifyPropertyChanged (MVVM Light ViewModelBase делает это за вас)
-
Свойство SelectedMovie должно вызывать событие PropertyChanged в своем установщике. Если вы используете MVVM Light, ViewModelBase предоставляет установленный метод для выполнения этого за вас.
Пример (с использованием MVVM Light; обратите внимание, что я опустил много деталей, чтобы сосредоточиться на основной проблеме):
<Window
DataContext={Binding MyViewModel, Source={StaticResource Locator}}
>
<ListBox x:Name="moviesListBox" ItemsSource="{Binding Movies}" SelectedItem="{Binding SelectedMovie, Mode=TwoWay}" />
<ListBox x:Name="actorsListBox" ItemsSource="{Binding SelectedMovie.Actors}" SelectedItem="{Binding SelectedActor, Mode=TwoWay}" />
</Window>
public MovieViewModel : ViewModelBase
{
public ObservableCollection<IMovie> Movies { get; } = new ObservableCollection<IMovie>();
public MovieViewModel()
{
foreach (var movie in blc.GetAllMovies())
Movies.Add(movie);
}
private Movie _selectedMovie;
public Movie SelectedMovie
{
get
{
return _selectedValue;
}
set
{
Set(ref _selectedValue, value);
}
}
}
public class ViewModelLocator
{
// Constructor to register ViewModels, etc...
//
public MovieViewModel MyViewModel => /* resolve the view model */
}
Ответ №2:
В вашем SelectedMovie
свойстве нет MovieViewModel
свойства. Вы должны добавить его и вызывать PropertyChanged
событие всякий раз, когда оно установлено, как предложено @C Robinson, или вы могли бы привязаться непосредственно к SelectedItem
свойству moviesListBox
:
<ListBox x:Name="actorsListBox" ItemsSource="{Binding SelectedItem.Actors, ElementName=actorsListBox}"
SelectedItem="{Binding SelectedActor, Mode=TwoWay}" />
Ответ №3:
В вашем SelectedActor
свойстве нет ViewModel
свойства.
ViewModel
public ObservableCollection<IMovie> Movies { get; set; } = new ObservableCollection<IMovie>();
private IMovie _selectedMovie
public IMovie SelectedMovie
{
get => _selectedMovie;
set
{
_selectedMovie = value;
RaisePropertyChanged(nameof(SelectedMovie));
}
}
Поэтому, когда вы будете выбирать фильм, будет вызван установщик SelectedMovie. Там это вызовет событие изменения свойства для SelectedMovie, а затем пользовательский интерфейс обновит второй список.