Как исправить «Ссылка на объект не установлена ​​для экземпляра объекта».при привязке события к элементу, сгенерированному ListView ItemsSource при использовании MVVM? - PullRequest
0 голосов
/ 02 апреля 2019

У меня есть ListView с ItemsSource, установленным на вид коллекции Movies (с объектами Movie).И тогда внутри у меня есть DataTemplate, который содержит ComboBox и TextBlock.В ComboBox я привязываю выбранный элемент к прогрессу (эпизодов), который содержит объект Movie.Здесь я использую обычный метод «Binding».Но проблема возникает, когда я хочу привязать метод к событию «DropDownClosed».Это прекрасно работает при использовании Code Behind, но использование ViewModel и x: Bind дает мне «Ссылка на объект не установлена ​​на экземпляр объекта».при создании моего приложения.

Целью является привязка к методу в ViewModel, а не к коду без ошибки.

Все работает гладко, когда я убираю событие "DropDownClosed".И никакие другие события не работают лучше.

<ListView ItemsSource="{x:Bind ViewModel.MovieLibrary}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel Spacing="20" Orientation="Horizontal">
                <ComboBox SelectedItem="{Binding Progress}"
                                          ItemsSource="{Binding Media.Episodes, Converter={StaticResource NumberToArrayConverter}}"
                                          DropDownClosed="{x:Bind ViewModel.UpdateStuff}">
                </ComboBox>
                <TextBlock Text="{Binding Media.Title}" TextWrapping="Wrap" />
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

И это, но это работает так же плохо, если оно пустое, поэтому idk, если это необходимо (из модели представления):

public void UpdateStuff(object sender, object e)
        {
            //blabla not important
        }

Проблема в том, что я не могу использовать x: Bind для любого свойства.

Ответы [ 2 ]

0 голосов
/ 03 апреля 2019

Я пытаюсь представить вам решение на небольшом примере.Вы увидите, что некоторые вещи изменились.Я надеюсь, что он все еще будет соответствовать вашим потребностям:

    <ListView ItemsSource="{Binding MovieLibrary}">
        <ListView.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <ComboBox  ItemsSource="{Binding Episodes}" 
                               SelectedItem="{Binding Progress}" >
                    </ComboBox>
                    <TextBlock Text="{Binding Title}" TextWrapping="Wrap" />
                </StackPanel>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>

, и это пример модели представления:

public class MainWindowModel
{
    public MainWindowModel()
    {
        MovieLibrary = new ObservableCollection<Media>();

        //
        //Exmaple Fill
        //
        var m1 = new Media() { Title = "Breaking Bad", Episodes = new List<string> { "1", "2", "3", "4", "5", "6" } };
        var m2 = new Media() { Title = "The Big Bang Theory", Episodes = new List<string> { "1", "2", "3" } };
        m1.MediaChangedAction += OnMediaChanged;
        m2.MediaChangedAction += OnMediaChanged;
        MovieLibrary.Add(m1);
        MovieLibrary.Add(m2);
    }
    public ObservableCollection<Media> MovieLibrary { get; set; }

    private void OnMediaChanged(Media movie)
    {
        // do something
    }

}

public class Media
{
    public event Action<Media> MediaChangedAction;

    public Media()
    {
    }

    public string Title { get; set; }
    public List<string> Episodes { get; set; }


    private string _progress;
    public string Progress
    {
        get { return _progress; }
        set
        {
            _progress = value;
            MediaChangedAction?.Invoke(this);
        }
    }
}

Вы видите, я немного упростил это (без конвертера и т. Д.).Также «событие» перемещается в модель представления.Что касается меня, то преимущество в том, что теперь оно не будет зависеть от представления для вызова события, это важно только для модели представления.Так что, если вы создадите другой вид для отображения мультимедиа, он все равно будет работать хорошо.

Я также исключил "двусторонние" вещи, поскольку на данный момент нет необходимости отправлять данные из модели представления ввид.При необходимости для «Media» должен быть реализован INotifyPropertyChanged.

0 голосов
/ 03 апреля 2019

Для использования x: Bind в DataTemplate необходимо указать x: DataType = "local: Movie" в DataTemplate.Путь в шаблоне x: Bind внутри шаблона должен быть относительно объекта Movie.

«Ссылка на объект не установлена» означает, что вы не указали указатель.Возможно, либо ViewModel имеет значение null, либо ViewModel.UpdateStuff имеет значение null.

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