Ошибка Listpicker SelectedItem всегда должен быть установлен в допустимое значение - PullRequest
10 голосов
/ 11 октября 2011

У меня есть страница в приложении Windows Phone 7, где пользователь может редактировать или удалять объект транзакции.Объект Transaction является классом Linq-to-Sql, который связан с классом Account и классом Category.На странице я использую ListPicker, чтобы позволить пользователю выбрать учетную запись и категорию для данной транзакции, например:

<toolkit:ListPicker Grid.Row="1" FullModeHeader="Choose the Account" FullModeItemTemplate="{StaticResource FullModeItemTemplate}" ExpansionMode="FullScreenOnly" Background="#26000000" Margin="10,0,10,0" Name="Account" SelectedItem="{Binding Account, Mode=TwoWay}" Tap="ListPicker_Tap" />

<toolkit:ListPicker Grid.Row="7" FullModeHeader="Choose the Category" FullModeItemTemplate="{StaticResource FullModeItemTemplate}" ExpansionMode="FullScreenOnly" Background="#26000000" Margin="10,0,10,0" Name="Category" SelectedItem="{Binding Category, Mode=TwoWay}" Tap="ListPicker_Tap" />

Событие ListPicker_Tap является исправлением ошибки в версии августа / 2011WPF Toolkit для Windows Phone и просто так:

    private void ListPicker_Tap(object sender, System.Windows.Input.GestureEventArgs e)
    {
        ListPicker lp = (ListPicker)sender; 
        lp.Open();
    }

Если пользователь редактирует транзакцию, все в порядке, но если пользователь пытается удалить ее, я получаю сообщение об ошибке, что «SelectedItem должен всегдаустановить правильное значение ".

Вот код, если пользователь нажимает кнопку" Удалить "на панели приложений в TransactionPage.xaml.cs:

    private void appBarDelete_Click(object sender, EventArgs e)
    {
        MessageBoxResult result = MessageBox.Show("Are you sure?\n", "Confirm", MessageBoxButton.OKCancel);

        if (result == MessageBoxResult.OK)
        {
            App.ViewModel.DeleteTransaction(transaction);
        }

        NavigationService.GoBack();
    }

Мой метод ViewModel.DeleteTransaction:

    public void DeleteTransaction(Transaction transaction)
    {
        AllTransactions.Remove(transaction);
        transactionRepository.Delete(transaction);
    }

Мой транзакцияRepository.Delete метод:

    public void Delete(Transaction transaction)
    {
        Context.Transactions.DeleteOnSubmit(transaction);
        Context.SubmitChanges();
    }

Я получаю ошибку при выполнении Context.SubmitChanges (), точки отладки NotifyPropertyChanged внутри класса Transactionстрока, где я получаю сообщение об ошибке:

    protected virtual void SendPropertyChanged(String propertyName)
    {
        if ((this.PropertyChanged != null))
        {
            this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

В атрибуте propertyName значение равно «Category».Похоже, что при удалении объекта отправляется событие propertychanged категории и учетных записей, и поскольку средство выбора списков находится в режиме TwoWay, у него возникают некоторые проблемы с ним.Как я мог это исправить?Мне нужна помощь.

Ответы [ 4 ]

12 голосов
/ 17 июня 2013

Эта ошибка также может быть вызвана порядком свойств XAML:

Это НЕ работает (выдает исключение, потому что ItemsSource имеет значение null, когда установлен SelectedItem):

<toolkit:ListPicker DisplayMemberPath="Title" SelectionMode="Single" 
SelectedItem="{Binding SelectedCategory, Mode=TwoWay}"
ItemsSource="{Binding Categories}" />

Это работает, так как источник элементов инициализируется первым:

<toolkit:ListPicker DisplayMemberPath="Title" SelectionMode="Single" 
ItemsSource="{Binding Categories}"
SelectedItem="{Binding SelectedCategory, Mode=TwoWay}" />
3 голосов
/ 04 июля 2013

ListPicker использует Items.IndexOf для получения индекса экземпляра элемента, который он должен выбрать.

Если экземпляр не совпадает (это не экземпляр объекта из коллекции), IndexOf вернет -1 иInvalidOperationException генерируется с сообщением: «SelectedItem всегда должен быть установлен на допустимое значение».

Переопределить метод Equals типа элемента в коллекции, и он будет работать как положено.

Пример:

public override bool Equals(object obj)
{
         var target = obj as ThisType;
         if (target == null)
             return false;

         if (this.ID == target.ID)
             return true;

         return false;
 }

Надеюсь, это поможет

2 голосов
/ 09 сентября 2012

Есть только две проверки, которые генерируют исключение InvalidOperationException для SelectedItem

  1. Элементы списков отсутствуют (Декларативный: порядок атрибутов имеет значение. Если selecteditem должен появиться после itemsource (Programatic: убедитесь, что источник данных загружен)
  2. Listpicker применяет Indexof для элементов, чтобы установить выбранный элемент. Поэтому убедитесь, что вы переопределяете Equals при необходимости.

Отладка с помощью watch на listpicker.Items и переопределенный метод Equals помогут нам определить проблему

1 голос
/ 11 октября 2011

Проблема в том, что ListPicker ожидает, что SelectedItem будет ListPickerItem, тогда как вы привязываете его к объекту типа Transaction. Вы можете обойти эту проблему, привязав вместо этого свойство SelectedIndex, а затем выберите соответствующий объект в ViewModel на основе индекса.

Кроме того, если причина, по которой вы определили обработчик Tap, связана с ошибкой, из-за которой ListPicker не открывается при помещении в ScrollViewer, взгляните на ID патча 10247, Если вы перекомпилируете инструментарий с этим патчем, это устранит проблему.

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