This is a migrated thread and some comments may be shown as answers.

Pesistence Manager Not Calling RestoreValue

2 Answers 132 Views
PersistenceFramework
This is a migrated thread and some comments may be shown as answers.
Greg Duffield
Top achievements
Rank 1
Greg Duffield asked on 21 Sep 2011, 12:46 PM
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 Answers, 1 is accepted

Sort by
0
Greg Duffield
Top achievements
Rank 1
answered on 22 Sep 2011, 09:36 AM
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


0
Alex Fidanov
Telerik team
answered on 26 Sep 2011, 04:59 PM
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 >>

Tags
PersistenceFramework
Asked by
Greg Duffield
Top achievements
Rank 1
Answers by
Greg Duffield
Top achievements
Rank 1
Alex Fidanov
Telerik team
Share this question
or