Pesistence Manager Not Calling RestoreValue

3 posts, 0 answers
  1. Greg Duffield
    Greg Duffield avatar
    38 posts
    Member since:
    Feb 2006

    Posted 21 Sep 2011 Link to this post

    I have implemented a CustomePropertyProvider for my TileView and I am attepting to save and restore the positions of the tiles at the moment. I can save the Positions and write these to isolated storage. However when I read these back the manage does not seem to be firing the RestoreValue Method on my class, but it did call the ProvideValue Method when saving.

    Class Implementing ICustomPropertyProvider
    public class TileViewCustomPropertyProvider : ICustomPropertyProvider
        {
            public CustomPropertyInfo[] GetCustomProperties()
            {
                return new CustomPropertyInfo[]
                {
                    new CustomPropertyInfo("Layout", typeof(Dictionary<string,int>))
                };
            }
     
            public void InitializeObject(object context)
            {
     
            }
     
            public object InitializeValue(CustomPropertyInfo customPropertyInfo, object context)
            {
                return null;
            }
     
            public object ProvideValue(CustomPropertyInfo customPropertyInfo, object context)
            {
                RadTileView tileView = context as RadTileView;
                if (customPropertyInfo.Name == "Layout")
                {
                    Dictionary<string, int> positions = new Dictionary<string, int>();
                    foreach (RadTileViewItem tile in tileView.Items)
                    {
                        positions.Add(tile.Name, tile.Position);
                    }
                    return positions;
                }
                return null;
            }
     
            public void RestoreValue(CustomPropertyInfo customPropertyInfo, object context, object value)
            {
                RadTileView tileView = context as RadTileView;
                Dictionary<string, int> positions = value as Dictionary<string, int>;
                if (customPropertyInfo.Name == "layout")
                {
                    foreach (RadTileViewItem tile in tileView.Items)
                    {
                        int position = -1;
                        if (positions.TryGetValue(tile.Name, out position))
                            tile.Position = position;
     
     
                    }
                }
            }

    Code for Saving:-
    PersistenceManager manager = new PersistenceManager();
    stream = manager.Save(this.rtvDashboard);
    using (var store = IsolatedStorageFile.GetUserStoreForApplication())
    {
    var fs = store.CreateFile("dashboardLayout");
    byte[] bytes = new byte[stream.Length];
    fs.Write(bytes, 0, (int)stream.Length);
    }

    Code for Loading
    private void LoadSettings()
           {
               PersistenceManager manager = new PersistenceManager();
               using (var store = IsolatedStorageFile.GetUserStoreForApplication())
               {
                   if (store.FileExists("dashboardlayout"))
                   {
                       var fs = store.OpenFile("dashboardLayout", FileMode.Open);
                       fs.Position = 0L;
                       manager.Load(this.rtvDashboard, fs);
                   }
               }
                
           }
    This is called from the Constrctor of the userControl
    public MainPage()
           {
               
     
               InitializeComponent();
               this.btnSaveLayout.Click += new RoutedEventHandler(btnSaveLayout_Click);
               ServiceProvider.RegisterPersistenceProvider<ICustomPropertyProvider>(typeof(RadTileView), new TileViewCustomPropertyProvider());
               LoadSettings();
                
           }

    Any help would be appreciated as I get no errors.Thanks

    Greg
  2. Greg Duffield
    Greg Duffield avatar
    38 posts
    Member since:
    Feb 2006

    Posted 22 Sep 2011 Link to this post

    I have been looking further into this and it shows that the persistencemanager is having issues loading the stream back again. It always throws an error about the format of the xml.

    I have been playing ith the Docking persistence example, and I have found that the same thing is happening here, if you add a handler to the persistanceerror event you will see that this errors when you call load passing in the stream. the error (stacktrace below) relates to the XML even though this has not been changed between the save and load calls. This then results in the manager not calling any restore events etc.

       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, Object events)
       at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle)
       at System.Xml.Serialization.XmlSerializer.Deserialize(Stream stream)
       at Telerik.Windows.Persistence.Serialization.Deserializer.Deserialize(Stream stream, Object objectToDeserialize)

    I would have to guess that this is a bug, and as such I will have to implement my own persistence handling.

    Thanks

    Greg


  3. DevCraft banner
  4. Alex Fidanov
    Admin
    Alex Fidanov avatar
    636 posts

    Posted 26 Sep 2011 Link to this post

    Hi Greg Duffield,

    First thing that I notice is that in the RestoreValue method you will never get pass the if clause, as the property that you have defined is "Layout" and you are checking for "layout". On my end, the code does enter this method, but the value parameter has zero count. This is because the PersistenceFramework cannot recreate a dictionary. Please try using a collection like List instead.

    However, if you are just using the custom property provider to save the position, you do not need it. The PersistenceFramework is capable of saving the Position property without any custom handling. It is a public value type property on the TileViewItem and it will be saved and loaded correctly. Moreover, we have an isolated storage provider, which handles the isolated storage logic out of the box. What you need to use is :

    <telerik:RadTileView Margin="0,20,0,0" telerik:PersistenceManager.StorageId="tileView">
         <telerik:RadTileViewItem Header="1"/>
         <telerik:RadTileViewItem Header="2"/>
         <telerik:RadTileViewItem Header="3"/>
         <telerik:RadTileViewItem Header="4"/>
     </telerik:RadTileView>

    // save and load:
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        new IsolatedStorageProvider().SaveToStorage();
    }
     
    private void Button_Click_1(object sender, RoutedEventArgs e)
    {
        new IsolatedStorageProvider().LoadFromStorage();
    }

    Furthermore, you can choose only some properties to be saved by using serialization options, like :

          <telerik:RadTileView Margin="0,20,0,0" telerik:PersistenceManager.StorageId="tileView">
                <telerik:PersistenceManager.SerializationOptions>
                    <telerik:SerializationMetadataCollection>
                        <telerik:PropertyNameMetadata Condition="Only" Expression="Position" SearchType="PropertyName" IsRecursive="True" />
                        <telerik:PropertyNameMetadata Condition="Only" Expression="State" SearchType="PropertyName" IsRecursive="True" />
                    </telerik:SerializationMetadataCollection>
                </telerik:PersistenceManager.SerializationOptions>
    ....


    Kind regards,
    Alex Fidanov
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

Back to Top