Windows Phone 7 ListPicker InvalidCastException

时间:2012-07-16 23:26:39

标签: c# silverlight windows-phone-7 data-binding

我在WP7中构建一个简单的crud表单时遇到了问题。我花了很多时间将枚举显示到listpicker中,现在我在尝试绑定到(IsolatedStorage)对象时看到InvalidCastException。

public class Bath {
   public string Colour { get; set; }
   public WaterType WaterType { get; set; }
}

public enum WaterType {
   Hot,
   Cold
}

枚举绑定到ListPicker,但由于WP7中没有enum.GetValues(),因此这不是一项简单的任务。

我有一个简单的类型类......

public class TypeList
    {
        public string Name { get; set; }
    }

在我的viewmodel中,我有ObservableCollection并模拟枚举中的值......

    private ObservableCollection<TypeList> _WaterTypeList;
    public ObservableCollection<TypeList> WaterTypeList
    {
        get { return _WaterTypeList; }
        set
        {
            _WaterTypeList= value;
            NotifyPropertyChanged("WaterTypeList");
        }
    }

    public void LoadCollectionsFromDatabase()
    {
        ObservableCollection<TypeList> wTypeList = new ObservableCollection<WaterTypeList>();
        wTypeList.Add(new TypeList{ Name = WaterType.Hot.ToString() });
        wTypeList.Add(new TypeList{ Name = WaterType.Income.ToString() });
        WaterTypeList = new ObservableCollection<TypeList>(wTypeList);
    }

最后,我的xaml包含列表框......

<toolkit:ListPicker
            x:Name="BathTypeListPicker"
            ItemsSource="{Binding WaterTypeList}"
            DisplayMemberPath="Name">
        </toolkit:ListPicker>

我不确定以上是否是最佳做法,如果以上是问题的一部分,但上面确实给了我一个填充的ListPicker。

最后,当提交表单时,强制转换会导致InvalidCastException。

 private void SaveAppBarButton_Click(object sender, EventArgs e)
{
    var xyz = WaterTypeList.SelectedItem; // type AppName.Model.typeList

        Bath b = new Bath
        {
            Colour = ColourTextBox.Text ?? "Black",
            WaterType = (WaterType)WaterTypeListPicker.SelectedItem
        };

        App.ViewModel.EditBath(b);
        NavigationService.Navigate(new Uri("/Somewhere.xaml", UriKind.Relative));
    }
}

有没有人遇到过类似问题,可以提供建议。我看到我的选择是专注于从ListPicker中构建有意义的东西,还是应该重新思考ListPicker的填充方式?

2 个答案:

答案 0 :(得分:3)

据我所知,WaterTypeList是一个ObservableCollection,它是一个Type,而一个可观察的集合没有SelectedItem属性。

您的Bath类有一个接受WaterType属性的WaterType,并且您正在尝试向其投射一个WaterTypeListPicker.SelectedItem ..所以我假设您的WatertypeListPicker是您的ListBox?

如果是,那么你做错了,因为你的ListBox的itemssource绑定到一个类,你试图将一个类添加到你的WaterType属性。

我要做的就是说,

Bath b = new Bath
        {
            Colour = ColourTextBox.Text ?? "Black",
            WaterType = WaterTypeListPicker.SelectedItem
        };

将Bath的 WaterType 的属性更改为 TypeList ,以便上述代码可以正常工作。但我不会建议另外一个类包装枚举只是为了将它显示在列表框中。

我要做的是创建一个EnumHelper

public static class EnumExtensions
{
    public static T[] GetEnumValues<T>()
    {
        var type = typeof(T);
        if (!type.IsEnum)
            throw new ArgumentException("Type '" + type.Name + "' is not an enum");

        return (
          from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
          where field.IsLiteral
          select (T)field.GetValue(null)
        ).ToArray();
    }

    public static string[] GetEnumStrings<T>()
    {
        var type = typeof(T);
        if (!type.IsEnum)
            throw new ArgumentException("Type '" + type.Name + "' is not an enum");

        return (
          from field in type.GetFields(BindingFlags.Public | BindingFlags.Static)
          where field.IsLiteral
          select field.Name
        ).ToArray();
    }
}

并将其绑定到集合

我的 ViewModel

public IEnumerable<string> Priority
        {
            get { return EnumExtensions.GetEnumValues<Priority>().Select(priority => priority.ToString()); }

public string SelectedPriority
        {
            get { return Model.Priority; }
            set { Model.Priority = value; }
        }

就像那样。

我的 XAML

<telerikInput:RadListPicker SelectedItem="{Binding SelectedPriority, Mode=TwoWay}" ItemsSource="{Binding Priority}" Grid.Column="1" Grid.Row="4"/>

答案 1 :(得分:1)

WaterTypeListPicker.SelectedItemTypeList类型的对象,因此无法强制转换为WaterType类型的对象。

为了转换回WaterType,你可以替换你的演员:

WaterType = (WaterType)WaterTypeListPicker.SelectedItem

使用:

WaterType = (WaterType)Enum.Parse(
                               typeof(WaterType),
                               ((TypeList)WaterTypeListPicker.SelectedItem).Name,
                               false)