简体   繁体   English

从SelectedItem绑定ItemsSource

[英]Bind ItemsSource from SelectedItem

This is my data structure: 这是我的数据结构:

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

And this is my viewModel: 这是我的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);
        }
    }

In my MainWindow I'am adding dataContext by this: 在我的MainWindow我以此添加dataContext

this.DataContext = new MovieViewModel();

I have 2 listboxes. 我有2个列表框。 When I select a movie in first listbox I want to display all actors in second listbox. 当我在第一个列表框中选择电影时,我想在第二个列表框中显示所有演员。

I managed to display movies. 我设法放映电影。 For some reason actors arent displayed when clicking on any movie. 由于某些原因,演员在点击任何电影时都无法显示。

<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}" />

What's wrong there? 那有什么不对?

You haven't shown where/how SelectedMovie is defined (how it exists in its viewmodel), but 您尚未显示SelectedMovie的定义位置/方式(其在视图模型中的存在方式),但是

  1. The viewmodel in which SelectedMovie is contained (presumably DataContext of the form/page containing the ListBox controls) must implement the INotifyPropertyChanged interface (the MVVM Light ViewModelBase does this for you) 包含SelectedMovie的视图模型(可能是包含ListBox控件的表单/页面的DataContext)必须实现INotifyPropertyChanged接口(MVVM Light ViewModelBase为您完成此操作)

  2. The SelectedMovie property must raise the PropertyChanged event in its setter. SelectedMovie属性必须在其setter中引发PropertyChanged事件。 If you are using MVVM Light, ViewModelBase provides a Set method to do this for you. 如果您使用的是MVVM Light,则ViewModelBase提供了Set方法来为您执行此操作。

Example (using MVVM Light; note I've omitted a lot of details to focus on the core issue): 示例(使用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 */
}

There is no SelectedMovie property in your MovieViewModel . MovieViewModel没有SelectedMovie属性。 You should add one and raise the PropertyChanged event whenever it's set as suggested by @C Robinson, or you could bind directly to the SelectedItem property of the moviesListBox : 只要按@C Robinson的建议进行设置,就应该添加一个并引发PropertyChanged事件,或者可以直接绑定到moviesListBoxSelectedItem属性:

<ListBox x:Name="actorsListBox" ItemsSource="{Binding SelectedItem.Actors, ElementName=actorsListBox}"
                                SelectedItem="{Binding SelectedActor, Mode=TwoWay}" />

There is no SelectedActor property in your ViewModel . 您的ViewModel没有SelectedActor属性。

ViewModel 视图模型

public ObservableCollection<IMovie> Movies { get; set; } = new ObservableCollection<IMovie>();

private IMovie _selectedMovie
public IMovie SelectedMovie
{
   get => _selectedMovie;
   set
   {
      _selectedMovie = value;
      RaisePropertyChanged(nameof(SelectedMovie));
   }
}

So when you will select a movie, SelectedMovie setter will be called. 因此,当您选择电影时,将调用SelectedMovie setter。 There it will raise property changed event for SelectedMovie, and then UI will update the second list. 在那里它将引发SelectedMovie的属性更改事件,然后UI将更新第二个列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM