我在Windows Phone 7应用程序中有一个页面,用户可以在其中编辑或删除Transaction对象。 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事件修复了8月/ 2011版WPF Toolkit for Windows Phone中的错误,只是这样:
private void ListPicker_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
ListPicker lp = (ListPicker)sender;
lp.Open();
}
如果用户编辑事务,一切都很好,但如果用户尝试删除它,我会收到一条错误消息,说“SelectedItem必须始终设置为有效值”。
如果用户点击TransactionPage.xaml.cs中appbar中的删除按钮,则代码如下:
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()执行中收到错误,调试指向Transaction类中的NotifyPropertyChanged,我得到错误的行是:
protected virtual void SendPropertyChanged(String propertyName)
{
if ((this.PropertyChanged != null))
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
在propertyName属性中,值为“Category”。看起来当删除对象时发送类别和帐户的propertychanged事件,并且因为listpicker处于TwoWay模式,所以在处理它时遇到一些麻烦。我该怎么办呢?我需要一些帮助。
答案 0 :(得分: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 :(得分:3)
ListPicker使用Items.IndexOf来获取它应该选择的项目实例的索引。
如果实例不匹配(它不是集合中的对象实例),IndexOf将返回-1并抛出InvalidOperationException并显示消息:“SelectedItem必须始终设置为有效值”。
覆盖集合中项目类型的等于方法,它将按预期工作。
示例:
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 :(得分:2)
只有两个检查会在SelectedItem
上抛出InvalidOperationException使用watchpicker.Items上的watch进行调试并覆盖Equals方法将帮助我们识别问题
答案 3 :(得分:1)
问题在于ListPicker
期望SelectedItem
为ListPickerItem
,而您将其绑定到Transaction
类型的对象。您可以通过绑定到SelectedIndex
属性来解决问题,然后根据索引从ViewModel中选择适当的对象。
此外,如果您定义Tap
处理程序的原因是由于ListPicker
放置在ScrollViewer
内时{{1}}未打开的错误,请查看{{3 }}。如果您使用该补丁重新编译工具包,则可以解决问题。