2012-05-25 42 views
0

我试图达成此目标:将Silverlight应用程序的状态保存到isolateduserstorage,以便在下次启动时重新加载它。我需要存储一个List ObservableCollection<UIElement>UIElements是由工厂创建的(实际上我在那里创建了Shapes)。序列化Silverlight XML UIElement

问题是,Serialization引发异常(您将在下面找到)。我有一个线索可能是什么问题(Serialization不知道如何存储UIElements(?)),但是,我不知道如何解决这个问题。

例外:

System.InvalidOperationException was unhandled by user code 
    Message=There was an error generating the XML document. 
    StackTrace: 
     bei System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id) 
     bei System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle) 
     bei System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces) 
     bei System.Xml.Serialization.XmlSerializer.Serialize(Stream stream, Object o, XmlSerializerNamespaces namespaces) 
     bei System.Xml.Serialization.XmlSerializer.Serialize(Stream stream, Object o) 
     bei Dojo_2_wi10b012.ViewModel.ViewModel.StoreContent() 
     bei Dojo_2_wi10b012.ViewModel.RelayCommand.Execute(Object parameter) 
     bei System.Windows.Controls.Primitives.ButtonBase.ExecuteCommand() 
     bei System.Windows.Controls.Primitives.ButtonBase.OnClick() 
     bei System.Windows.Controls.Button.OnClick() 
     bei System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e) 
     bei System.Windows.Controls.Control.OnMouseLeftButtonUp(Control ctrl, EventArgs e) 
     bei MS.Internal.JoltHelper.FireEvent(IntPtr unmanagedObj, IntPtr unmanagedObjArgs, Int32 argsTypeIndex, Int32 actualArgsTypeIndex, String eventName, UInt32 flags) 
    InnerException: System.InvalidOperationException 
     Message=The type System.Windows.Shapes.Ellipse was not expected. Use the XmlInclude attribute to specify types that are not known statically. 
     StackTrace: 
      bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterObservableCollection1.Write12_UIElement(String n, String ns, UIElement o, Boolean isNullable, Boolean needType) 
      bei Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterObservableCollection1.Write13_ArrayOfUIElement(Object o) 
     InnerException: 

视图模型:(重要的部分是方法 “StoreContent()”)

using System; 
using System.Net; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Documents; 
using System.Windows.Ink; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Animation; 
using System.Windows.Shapes; 
using Dojo_2_wi10b012.Model; 
using System.ComponentModel; 
using System.Reflection; 
using System.IO.IsolatedStorage; 
using System.IO; 
using System.Xml.Serialization; 

namespace Dojo_2_wi10b012.ViewModel 
{ 
    public class ViewModel : INotifyPropertyChanged 
    { 
     private List<UIElement> _shapeList = new List<UIElement>(); 
     private ShapeFactory theFactory = new ShapeFactory(); 
     private ObservableCollection<UIElement> _elements = new ObservableCollection<UIElement>(); 
     private UIElement _selectedItem ; 
     private UIElement _alteredSelectedItem; 
     private ObservableCollection<KeyValuePair<string, Color>> _theColors = new ObservableCollection<KeyValuePair<string, Color>>(); 
     private KeyValuePair<string, Color> _selectedBrush = new KeyValuePair<string, Color>(); 
     private KeyValuePair<string, Color> _selectedStroke = new KeyValuePair<string, Color>(); 
     private SolidColorBrush _selectedBrushBrush = new SolidColorBrush(); 
     private SolidColorBrush _selectedStrokeBrush = new SolidColorBrush(); 
     private int _heightText; 
     private int _widthText; 
     private string filename = "uielements"; //for isolatedstorage   

     #region EventHandler 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected void NotifyPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
     #endregion 

     public ViewModel() 
     { 
      GetShapesCommand = new RelayCommand(GetShapes); 
      GetShapesCommand.IsEnabled = true; 
      LoadColors(); 
      ChangeShapeCommand = new RelayCommand(ChangeShape); 
      ChangeShapeCommand.IsEnabled = true; 
      StoreContentCommand = new RelayCommand(StoreContent); 
      StoreContentCommand.IsEnabled = true; 
     } 

     #region properties 

     public int HeightText 
     { 
      get { return _heightText; } 
      set 
      { 
       _heightText = value; 
       NotifyPropertyChanged("HeightText"); 
      } 
     } 

     public int WidthText 
     { 
      get { return _widthText; } 
      set 
      { 
       _widthText = value; 
       NotifyPropertyChanged("WidthText"); 
      } 
     } 

     public SolidColorBrush SelectedBrushBrush 
     { 
      get { return _selectedBrushBrush; } 
      set 
      { 
       _selectedBrushBrush = value; 
       NotifyPropertyChanged("SelectedBrushBrush"); 
      } 
     } 

     public SolidColorBrush SelectedStrokeBrush 
     { 
      get { return _selectedStrokeBrush; } 
      set 
      { 
       _selectedStrokeBrush = value; 
       NotifyPropertyChanged("SelectedStrokeBrush"); 
      } 
     } 

     public KeyValuePair<string, Color> SelectedBrush 
     { 
      get { return _selectedBrush; } 
      set 
      { 
       _selectedBrush = value; 
       NotifyPropertyChanged("SelectedBrush"); 
       SelectedBrushBrush = new SolidColorBrush(value.Value); 
      } 
     } 

     public KeyValuePair<string, Color> SelectedStroke 
     { 
      get { return _selectedStroke; } 
      set 
      { 
       _selectedStroke = value; 
       NotifyPropertyChanged("SelectedStroke"); 
       SelectedStrokeBrush = new SolidColorBrush(value.Value); 
      } 
     } 

     public ObservableCollection<KeyValuePair<string, Color>> TheColors 
     { 
      get { return _theColors; } 
      set 
      { 
       _theColors = value; 
       NotifyPropertyChanged("TheColors"); 
      } 
     } 

     public List<UIElement> ShapeList 
     { 
      get { return _shapeList; } 
      set 
      { 
       _shapeList = value; 
       NotifyPropertyChanged("ShapeList"); 
      } 
     } 

     public ObservableCollection<UIElement> Elements 
     { 
      get { return _elements; } 
      set 
      { 
       _elements = value; 
       NotifyPropertyChanged("Elements"); 
      } 
     } 

     public UIElement SelectedItem 
     { 
      get { return _selectedItem; } 
      set 
      { 
       _selectedItem = value; 
       NotifyPropertyChanged("SelectedItem"); 
      } 
     } 

     public UIElement AlteredSelectedItem 
     { 
      get { return _alteredSelectedItem; } 
      set 
      { 
       _alteredSelectedItem = value; 
       NotifyPropertyChanged("AlteredSelectedItem"); 
      } 
     } 

     public RelayCommand GetShapesCommand { get; private set; } 
     public RelayCommand ChangeShapeCommand { get; private set; } 
     public RelayCommand StoreContentCommand { get; private set; } 


     #endregion 

     #region PrivateMethods 
     private void GetShapes() 
     { 
      UIElement temp = theFactory.ProduceShape(); 
      temp.MouseLeftButtonDown += Handle_MouseDown; 
      temp.MouseMove += Handle_MouseMove; 
      temp.MouseLeftButtonUp += Handle_MouseUp; 
      temp.MouseRightButtonDown += Handle_RightMouseDown; 
      ShapeList.Add(temp); //add the new shape to the list where we store the shapes 
      Elements.Add(temp); 
     } 

     private void ChangeShape() 
     { 
      AlteredSelectedItem = SelectedItem; 
      Shape temp = FigureOutShape(AlteredSelectedItem); 
      double debugheight = temp.Height; 
      double debugwidth = temp.Width; 
      temp.Height = HeightText; 
      temp.Width = WidthText; 
      temp.Fill = SelectedBrushBrush; 
      temp.Stroke = SelectedStrokeBrush; 
      SelectedItem = (UIElement)temp; 
     } 

     private Shape FigureOutShape(UIElement input) 
     { 
      if (input != null) 
      { 
       if (input is Ellipse) 
       { 
        return (Ellipse)input; 
       } 
       else { return (Rectangle)input; } 
      } 
      else //default if the user hasn't selected a shape 
       return new Ellipse() 
       { 
        Width = 25, 
        Height = 25, 
        Stroke = new SolidColorBrush(Colors.Green), 
        Fill = new SolidColorBrush(Colors.DarkGray), 
        StrokeThickness = 2, 
        Visibility = Visibility.Visible, 
        Cursor= Cursors.Hand, 
        Margin = new Thickness(25, 30, 0, 0) //define initial position on canvas randomly 
       }; 
     } 

     private void StoreContent() 
     { 
      //Hint from Mr. Eckkrammer (wiki): 
      using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()) 
      { 
       IsolatedStorageFileStream isoRegisterFileStream; 

       isoRegisterFileStream = new IsolatedStorageFileStream(filename, FileMode.Create, isf); 

       XmlSerializer serializer = new XmlSerializer(Elements.GetType()); 

       serializer.Serialize(isoRegisterFileStream, Elements); 

       //close file stream 
       isoRegisterFileStream.Close(); 
      } 

     } 

     private void LoadContent() 
     { 
      /* 
      try 
      { 
      Elements as ObservableCollection<UIElement> = IsolatedStorageSettings.ApplicationSettings(filename); 
      } 
      catch 
      { 
      //no idea what to do here... 
      } 
      */ 
      using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication()) 
      { 
       using (IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(filename, FileMode.Open, isf)) 
       { 
        using (StreamReader sr = new StreamReader(isfs)) 
        { 

         // string lineOfData = String.Empty; 
         // while ((lineOfData = sr.ReadLine()) != null) 
         // data += lineOfData; 

         //no idea what to do here... 

        } 
       } 
      } 


     } 



     //when the user right clicks a shape, the "selectedItem" will be updated 
     private void Handle_RightMouseDown(object sender, MouseEventArgs args) 
     { 
      UIElement item = sender as UIElement; 
      SelectedItem = item; 
     } 

     private void LoadColors() 
     { 
      //unfortunately I have no idea how to do the following automatically, so I need to do it by hand :-(
      TheColors.Add(new KeyValuePair<string,Color>("Black",Colors.Black)); 
      TheColors.Add(new KeyValuePair<string,Color>("Blue",Colors.Blue)); 
      TheColors.Add(new KeyValuePair<string,Color>("Brown",Colors.Brown)); 
      TheColors.Add(new KeyValuePair<string,Color>("Cyan",Colors.Cyan)); 
      TheColors.Add(new KeyValuePair<string,Color>("DarkGray",Colors.DarkGray)); 
      TheColors.Add(new KeyValuePair<string,Color>("Gray",Colors.Gray)); 
      TheColors.Add(new KeyValuePair<string,Color>("Green",Colors.Green)); 
      TheColors.Add(new KeyValuePair<string, Color>("LightGray", Colors.LightGray)); 
      TheColors.Add(new KeyValuePair<string,Color>("Magenta",Colors.Magenta)); 
      TheColors.Add(new KeyValuePair<string,Color>("Orange",Colors.Orange)); 
      TheColors.Add(new KeyValuePair<string,Color>("Purple",Colors.Purple)); 
      TheColors.Add(new KeyValuePair<string,Color>("Red",Colors.Red)); 
      TheColors.Add(new KeyValuePair<string,Color>("White",Colors.White)); 
      TheColors.Add(new KeyValuePair<string,Color>("Yellow",Colors.Yellow)); 
     } 
     #endregion 

     #region DragAndDropImplementation 

     private bool isMouseCaptured; 
     private double mouseVerticalPosition; 
     private double mouseHorizontalPosition; 

     private void Handle_MouseDown(object sender, MouseEventArgs args) 
     { 
      UIElement item = sender as UIElement; 
      mouseVerticalPosition = args.GetPosition(null).Y; 
      mouseHorizontalPosition = args.GetPosition(null).X; 
      isMouseCaptured = true; 
      item.CaptureMouse(); 
     } 

     private void Handle_MouseMove(object sender, MouseEventArgs args) 
     { 
      UIElement item = sender as UIElement; 
      if (isMouseCaptured) 
      { 

       // Calculate the current position of the object. 
       double deltaV = args.GetPosition(null).Y - mouseVerticalPosition; 
       double deltaH = args.GetPosition(null).X - mouseHorizontalPosition; 
       double newTop = deltaV + (double)item.GetValue(Canvas.TopProperty); 
       double newLeft = deltaH + (double)item.GetValue(Canvas.LeftProperty); 

       // Set new position of object. 
       item.SetValue(Canvas.TopProperty, newTop); 
       item.SetValue(Canvas.LeftProperty, newLeft); 

       // Update position global variables. 
       mouseVerticalPosition = args.GetPosition(null).Y; 
       mouseHorizontalPosition = args.GetPosition(null).X; 
      } 
     } 

     private void Handle_MouseUp(object sender, MouseEventArgs args) 
     { 
      UIElement item = sender as UIElement; 
      isMouseCaptured = false; 
      item.ReleaseMouseCapture(); 
      mouseVerticalPosition = -1; 
      mouseHorizontalPosition = -1; 
     } 
     #endregion 
    } 
} 

ShapeFactory.cs:

namespace Dojo_2_wi10b012.Model 
{ 
    public class ShapeFactory 
    { 
     Random ran; 
     Random xy; 
     int thick = 5; 
     public ShapeFactory() 
     { 
      ran = new Random(); 
      xy = new Random(); 
     } 

     public Shape ProduceShape() 
     { 
      int guess = ran.Next(0, 4); 
      int height = ran.Next(20, 80); 
      int width = ran.Next(20, 80); 
      int x = xy.Next(0,300); 
      int y = xy.Next(25,300); 

      if (guess == 0)//Ellipse 
       return new Ellipse() 
       { 
        Width = height, 
        Height = width, 
        Stroke = new SolidColorBrush(Colors.Green), 
        Fill = new SolidColorBrush(Colors.DarkGray), 
        StrokeThickness = thick, 
        Visibility = Visibility.Visible, 
        Cursor= Cursors.Hand, 
        Margin = new Thickness(x, y, 0, 0) //define initial position on canvas randomly 
       }; 
      else if (guess == 1) //Rectangle 
       return new Rectangle() 
       { 
        Width = height, 
        Height = width, 
        Stroke = new SolidColorBrush(Colors.Brown), 
        Fill = new SolidColorBrush(Colors.LightGray), 
        StrokeThickness = thick, 
        Visibility = Visibility.Visible, 
        Cursor = Cursors.Hand, 
        Margin = new Thickness(x, y, 0, 0) //define initial position on canvas randomly 
       }; 
      else if (guess == 2) //Square 
       return new Ellipse() 
       { 
        Width = height, 
        Height = height, 
        Stroke = new SolidColorBrush(Colors.Red), 
        StrokeThickness = thick, 
        Fill = new SolidColorBrush(Colors.Orange), 
        Visibility = Visibility.Visible, 
        Cursor = Cursors.Hand, 
        Margin = new Thickness(x, y, 0, 0) //define initial position on canvas randomly 
       }; 
      else //Circle 
       return new Rectangle() 
       { 
        Width = height, 
        Height = height, 
        Stroke = new SolidColorBrush(Colors.Blue), 
        StrokeThickness = thick, 
        Fill = new SolidColorBrush(Colors.Cyan), 
        Visibility = Visibility.Visible, 
        Cursor = Cursors.Hand,      
        Margin = new Thickness(x, y, 0, 0) //define initial position on canvas randomly 
       }; 
     } 
    } 
} 

回答

1

UIElement不支持序列,您将不得不将其序列化为XML作为字符串,将其保存到独立的存储或数据库,并将其反序列化从XML返回到视图模型。

0

您是否尝试过使用Xaml序列化服务?如果你是de /序列化xaml内容,最好使用那些而不是常规的xml序列化。 This博客文章描述了这一切。