2011-10-10 34 views
10

我在Windows Phone 7应用程序中有一个页面,用户可以在其中编辑或删除一个Transaction对象。 Transaction对象是一个与Account类和Category类有关系的Linq-to-Sql类。在该页面中,我使用ListPicker让用户选择指定交易的帐户和类别,如:Listpicker错误SelectedItem必须始终设置为有效值

<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事件是在八月/ 2011版的WPF的一个bug修复工具包的Windows Phone和很简单:

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

如果用户编辑的交易,一切都很好,但如果用户试图删除它,我得到一个错误说“的SelectedItem必须始终设置为有效值“。

下面的代码,如果用户点击删除按钮在appbar在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); 
    } 

我transactionRepository.Delete方法:

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

我在Context.SubmitChanges中收到错误()执行,调试点,交易类中的NotifyPropertyChanged,在那里我得到了错误的路线是这样的:

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

在propertyName的属性值是“类别”。它看起来像是在删除对象时发送类别和帐户的属性更改事件,并且由于listpicker处于双向模式,所以在处理它时遇到了一些麻烦。我怎么修复它?我需要一些帮助。

+0

您可以将完整的XAML?或者如果它太长,只要我们可以看到'{Binding Account,Mode = TwoWay}'和'{Binding Category,Mode = TwoWay}'指的是什么,部分XAML就可以。 – Amry

回答

1

问题是ListPicker期望SelectedItemListPickerItem,而您将其绑定到Transaction类型的对象。您可以通过绑定到SelectedIndex属性来解决问题,然后根据索引从ViewModel中选择适当的对象。

此外,如果您已经定义了Tap处理的原因是因为,当放置在ScrollViewerListPicker不开的bug,看看patch ID 10247。如果您使用该补丁重新编译工具包,它可以解决问题。

+0

'ListPicker.SelectedItem'也可以绑定到数据对象,而不仅仅是'ListPickerItem'。 – Amry

+0

@Amry你尝试过吗?我有完全相同的问题,必须解决使用'SelectedIndex' – Praetorian

+0

如果'ListPicker'是数据绑定,那么与'SelectedItem'一起使用数据对象应该可以正常工作。也许你可以为你的情况开一个新的问题。 :) – Amry

2

只有两项检查其抛出InvalidOperationException异常上的SelectedItem

  1. Listpicker项目为空 (声明:属性事宜命令,如果将selectedItem必须经过的ItemSource出现 (程序化:确保的ItemSource加载)
  2. Listpicker上的项目适用INDEXOF设置选定的项目。所以,必要时请确保你重写equals。

调试与开左表istpicker。项目和覆盖equals方法将帮助我们找出问题

+0

另请注意:如果你绑定到一个子属性,你还需要初始化它,否则你会遇到同样的错误(因为你的第一个属性为空)。 – kamranicus

12

此错误也可以通过XAML属性的顺序造成的:

这不起作用(抛出异常,因为当的SelectedItem被设置的ItemsSource为null ):

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

这个工程作为的ItemsSource第一次初始化:

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

是的,这显然是.NET控件中的一个错误,因为它应该处理这样的场景而不会崩溃......(设计你自己的控件时要考虑到这个问题:) –

+0

这个解决方案为我做了。 –

3

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

希望它可以帮助

相关问题