So I've seen the WPF demo app that shows how to use a PersistenceManager to save and load using a Stream. The demo works well, I have no issues with it...however I modified it to do the saving and loading during the Loaded and Unloaded events, and when this line of code is executed, it throws a NullReferenceException...
this.stream.Position = 0L;Which isn't shocking since I do not see anywhere that the Stream object is instantiated except when executing the line...
this.stream = manager.Save(this.gridView);So...I'm getting the feeling that a PersistenceManger object wasn't intended to be used between launches of an app...or am I just not understanding something here?
adfad
8 Answers, 1 is accepted
I found that I can get persisting between app launches working in the GridView demo if I use IsolatedStorageProvider instead of PersistenceManager and a Stream...however when I applied this to my own app, I'm getting odd results when trying to restore the column order.
If I reorder any of the columns, during the Load event where I'm using LoadFromStorage it loads up to the point where the first reordered column comes up then the grid stops being made and only the columns that came before the reordered column are displayed.
Here's the xaml and code behind for my control
001.<UserControl x:Class="ThirdPartyOptic.QualificationListUserControl"003. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"004. xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"005. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"006. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"007. xmlns:local="clr-namespace:ThirdPartyOptic"008. mc:Ignorable="d"009. d:DesignHeight="300"010. d:DesignWidth="300">011. <telerik:RadBusyIndicator IsIndeterminate="True"012. x:Name="QualificationListRadBusyIndicator">013. <Grid Background="Transparent">014. <Grid.ColumnDefinitions>015. <ColumnDefinition Width="175" />016. <ColumnDefinition />017. </Grid.ColumnDefinitions>018. <Grid.RowDefinitions>019. <RowDefinition Height="50" />020. <RowDefinition />021. <RowDefinition Height="Auto" />022. </Grid.RowDefinitions>023. <TextBlock FontSize="20"024. FontWeight="Bold"025. Grid.Column="1"026. Grid.Row="0"027. HorizontalAlignment="Left"028. Margin="10"029. Text="Qualification List"030. VerticalAlignment="Center" />031. <telerik:RadButton Click="ExportToExcelButton_Click"032. Content="Export to Excel"033. Grid.Column="1"034. Grid.Row="0"035. Height="30"036. HorizontalAlignment="Right" Margin="5, 5, 5, 5"037. VerticalAlignment="Center"038. x:Name="ExportToExcelButton" />039. <Grid Background="Transparent"040. Grid.Column="0"041. Grid.Row="1">042. <Grid.RowDefinitions>043. <RowDefinition Height="Auto" />044. <RowDefinition Height="Auto" />045. </Grid.RowDefinitions>046. <TextBlock FontWeight="Bold"047. Grid.Row="0"048. HorizontalAlignment="Center"049. Text="Show / Hide Columns" />050. <ListBox BorderBrush="Transparent"051. Grid.Row="1"052. ItemsSource="{Binding Columns, ElementName=QualificationListRadGridView}">053. <ListBox.ItemTemplate>054. <DataTemplate>055. <CheckBox Background="{Binding Header.Background}"056. IsChecked="{Binding IsVisible, Mode=TwoWay}">057. <TextBlock Background="{Binding Header.Background}"058. Text="{Binding Header.Text}"059. Width="140"/>060. </CheckBox>061. </DataTemplate>062. </ListBox.ItemTemplate>063. </ListBox>064. </Grid>065. <telerik:RadGridView AutoGenerateColumns="False"066. CanUserInsertRows="False"067. CanUserReorderColumns="True"068. CanUserResizeColumns="True"069. CanUserResizeRows="True"070. CanUserSelect="True"071. ColumnWidth="*"072. Filtered="QualificationListRadGridView_Filtered"073. Grid.Column="1"074. Grid.Row="1"075. RowEditEnded="QualificationListRadGridView_RowEditEnded"076. SelectionMode="Single"077. SelectionUnit="Cell"078. x:Name="QualificationListRadGridView" Loaded="QualificationListRadGridView_Loaded" telerik:PersistenceManager.StorageId="QualificationListRadGridView" Unloaded="QualificationListRadGridView_Unloaded">079. <telerik:RadGridView.Columns>080. <telerik:GridViewComboBoxColumn DataMemberBinding="{Binding TestStatusName}">081. <telerik:GridViewComboBoxColumn.Header>082. <TextBlock Text="Status" />083. </telerik:GridViewComboBoxColumn.Header>084. <telerik:GridViewComboBoxColumn.Resources>085. <Style TargetType="telerik:GridViewComboBoxColumn">086. <Setter Property="IsComboBoxEditable"087. Value="True" />088. </Style>089. </telerik:GridViewComboBoxColumn.Resources>090. </telerik:GridViewComboBoxColumn>091. <telerik:GridViewDataColumn DataMemberBinding="{Binding TransceiverCompatibilityName}"092. IsReadOnly="True">093. <telerik:GridViewDataColumn.Header>094. <TextBlock Background="Orange"095. Text="Compat" />096. </telerik:GridViewDataColumn.Header>097. </telerik:GridViewDataColumn>098. <telerik:GridViewDataColumn DataMemberBinding="{Binding TransceiverFormFactorName}"099. IsReadOnly="True">100. <telerik:GridViewDataColumn.Header>101. <TextBlock Background="Orange"102. Text="Form Factor" />103. </telerik:GridViewDataColumn.Header>104. </telerik:GridViewDataColumn>105. <telerik:GridViewDataColumn DataMemberBinding="{Binding TransceiverSupplierName}"106. IsReadOnly="True">107. <telerik:GridViewDataColumn.Header>108. <TextBlock Background="Orange"109. Text="Sup" />110. </telerik:GridViewDataColumn.Header>111. </telerik:GridViewDataColumn>112. <telerik:GridViewDataColumn DataMemberBinding="{Binding TransceiverPartNumber}"113. IsReadOnly="True">114. <telerik:GridViewDataColumn.Header>115. <TextBlock Background="Orange"116. Text="Part #" />117. </telerik:GridViewDataColumn.Header>118. </telerik:GridViewDataColumn>119. <telerik:GridViewDataColumn DataMemberBinding="{Binding TransceiverRevision}"120. IsReadOnly="True">121. <telerik:GridViewDataColumn.Header>122. <TextBlock Background="Orange"123. Text="Rev" />124. </telerik:GridViewDataColumn.Header>125. </telerik:GridViewDataColumn>126. <telerik:GridViewDataColumn DataMemberBinding="{Binding TransceiverBreakoutMode}"127. IsReadOnly="True">128. <telerik:GridViewDataColumn.Header>129. <TextBlock Background="Orange"130. Text="Breakout" />131. </telerik:GridViewDataColumn.Header>132. </telerik:GridViewDataColumn>133. <telerik:GridViewDataColumn DataMemberBinding="{Binding SwitchModel}"134. IsReadOnly="True">135. <telerik:GridViewDataColumn.Header>136. <TextBlock Background="Beige"137. Text="Model" />138. </telerik:GridViewDataColumn.Header>139. </telerik:GridViewDataColumn>140. <telerik:GridViewDataColumn DataMemberBinding="{Binding SwitchSupplierName}"141. IsReadOnly="True">142. <telerik:GridViewDataColumn.Header>143. <TextBlock Background="Beige"144. Text="Sup" />145. </telerik:GridViewDataColumn.Header>146. </telerik:GridViewDataColumn>147. <telerik:GridViewComboBoxColumn DataMemberBinding="{Binding SwitchOSName}">148. <telerik:GridViewComboBoxColumn.Header>149. <TextBlock Background="Beige"150. Text="Sup" />151. </telerik:GridViewComboBoxColumn.Header>152. <telerik:GridViewComboBoxColumn.Resources>153. <Style TargetType="telerik:GridViewComboBoxColumn">154. <Setter Property="IsComboBoxEditable"155. Value="True" />156. </Style>157. </telerik:GridViewComboBoxColumn.Resources>158. </telerik:GridViewComboBoxColumn>159. <telerik:GridViewDataColumn DataMemberBinding="{Binding ServerNetworkDeviceDisplayName}"160. IsReadOnly="True">161. <telerik:GridViewDataColumn.Header>162. <TextBlock Background="Olive"163. Text="NIC/FPGA" />164. </telerik:GridViewDataColumn.Header>165. </telerik:GridViewDataColumn>166. <telerik:GridViewDataColumn DataMemberBinding="{Binding ServerRecipe}"167. IsReadOnly="True">168. <telerik:GridViewDataColumn.Header>169. <TextBlock Background="Olive"170. Text="Recipe" />171. </telerik:GridViewDataColumn.Header>172. </telerik:GridViewDataColumn>173. <telerik:GridViewDataColumn DataMemberBinding="{Binding ServerSupplierName}"174. IsReadOnly="True">175. <telerik:GridViewDataColumn.Header>176. <TextBlock Background="Olive"177. Text="Sup" />178. </telerik:GridViewDataColumn.Header>179. </telerik:GridViewDataColumn>180. <telerik:GridViewComboBoxColumn DataMemberBinding="{Binding AssignedTo}">181. <telerik:GridViewComboBoxColumn.Header>182. <TextBlock Text="Assigned To" />183. </telerik:GridViewComboBoxColumn.Header>184. <telerik:GridViewComboBoxColumn.Resources>185. <Style TargetType="telerik:GridViewComboBoxColumn">186. <Setter Property="IsComboBoxEditable" Value="True" />187. </Style>188. </telerik:GridViewComboBoxColumn.Resources>189. </telerik:GridViewComboBoxColumn>190. <telerik:GridViewDataColumn DataMemberBinding="{Binding CertificationNumber}">191. <telerik:GridViewDataColumn.Header>192. <TextBlock Text="Cert #" />193. </telerik:GridViewDataColumn.Header>194. </telerik:GridViewDataColumn>195. <telerik:GridViewDataColumn DataMemberBinding="{Binding Comments}">196. <telerik:GridViewDataColumn.Header>197. <TextBlock Text="Comments" />198. </telerik:GridViewDataColumn.Header>199. </telerik:GridViewDataColumn>200. <telerik:GridViewHyperlinkColumn DataMemberBinding="{Binding TestResultLink}">201. <telerik:GridViewHyperlinkColumn.Header>202. <TextBlock Text="TR Link" />203. </telerik:GridViewHyperlinkColumn.Header>204. </telerik:GridViewHyperlinkColumn>205. <telerik:GridViewDataColumn DataMemberBinding="{Binding LastUpdate}"206. IsReadOnly="True">207. <telerik:GridViewDataColumn.Header>208. <TextBlock Text="Last Update" />209. </telerik:GridViewDataColumn.Header>210. </telerik:GridViewDataColumn>211. <telerik:GridViewDataColumn>212. <telerik:GridViewDataColumn.Header>213. <TextBlock Text="Row Cmds" />214. </telerik:GridViewDataColumn.Header>215. <telerik:GridViewDataColumn.CellTemplate>216. <DataTemplate>217. <telerik:RadButton Click="DeleteRadButton_Click"218. Content="Delete" />219. </DataTemplate>220. </telerik:GridViewDataColumn.CellTemplate>221. </telerik:GridViewDataColumn>222. </telerik:RadGridView.Columns>223. </telerik:RadGridView>224. <telerik:RadDataPager AutoEllipsisMode="Both"225. DisplayMode="All"226. Grid.Column="1"227. Grid.Row="2" 228. NumericButtonCount="10"229. PageSize="40"230. Source="{Binding Items, ElementName=QualificationListRadGridView}"231. VerticalAlignment="Bottom"232. x:Name="QualificationListRadDataPager" />233. </Grid>234. </telerik:RadBusyIndicator>235.</UserControl>
001.namespace ThirdPartyOptic002.{003. using Microsoft.Win32;004. using PhynetReporting;005. using System;006. using System.Collections.ObjectModel;007. using System.ComponentModel;008. using System.Configuration;009. using System.IO;010. using System.Linq;011. using System.Windows.Controls;012. using Telerik.Windows.Controls;013. using Telerik.Windows.Persistence;014. using Telerik.Windows.Persistence.Services;015. using Telerik.Windows.Persistence.Storage;016. using Telerik.Windows.PersistenceFramework;017. 018. /// <summary>019. /// Interaction logic for QualificationListUserControl.xaml020. /// </summary>021. public partial class QualificationListUserControl : UserControl022. {023. public QualificationListUserControl()024. {025. InitializeComponent();026. 027. if (DesignerProperties.GetIsInDesignMode(this))028. return;029. 030. DataMaintenance = new DataMaintenance(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);031. TransceiverToSwitchReporting = new TransceiverToSwitchReporting(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString);032. 033. BackgroundWorker = new BackgroundWorker();034. BackgroundWorker.DoWork += BackgroundWorkerDoWork;035. BackgroundWorker.RunWorkerCompleted += BackgroundWorkerCompleted;036. }037. 038. private Collection<string> AssignedToCollection { get; set; }039. 040. /// <summary>041. /// background working thread042. /// </summary>043. private BackgroundWorker BackgroundWorker { get; set; }044. 045. private DataMaintenance DataMaintenance { get; set; }046. 047. private DateTime LastUpdate { get; set; }048. 049. private Collection<string> SwitchOSNameCollection { get; set; }050. 051. private Collection<string> TestStatusCollection { get; set; }052. 053. private TransceiverToSwitchReporting TransceiverToSwitchReporting { get; set; }054. 055. /// <summary>056. /// runs the background worker thread to which refreshes the data source 057. /// for the control058. /// </summary>059. public void RefreshData()060. {061. if (!BackgroundWorker.IsBusy)062. {063. DateTime currentLastUpdate = DateTime.MinValue;064. var currentLastUpdateTimeResult = TransceiverToSwitchReporting.GetTransceiverSwitchQualificationListLastUpdateTime();065. 066. if(!currentLastUpdateTimeResult.Result)067. {068. Logging.LogMessage(currentLastUpdateTimeResult.Message, true);069. }070. else071. {072. currentLastUpdate = currentLastUpdateTimeResult.Payload;073. }074. 075. if (currentLastUpdate > LastUpdate)076. {077. QualificationListRadBusyIndicator.IsBusy = true;078. BackgroundWorker.RunWorkerAsync();079. }080. }081. }082. 083. private void BackgroundWorkerDoWork(object sender, DoWorkEventArgs e)084. {085. var assignedToCollectionResult = TransceiverToSwitchReporting.GetTransceiverSwitchQualificationListAssignedToValues();086. 087. if(!assignedToCollectionResult.Result)088. {089. string formattedMessage = string.Format(090. "There was an error while communicating with the database. Error from the Database: [{0}]",091. assignedToCollectionResult.Message);092. Logging.LogMessage(formattedMessage, true);093. }094. else095. {096. AssignedToCollection = assignedToCollectionResult.Payload;097. }098. 099. var switchOSNameCollectionResult = DataMaintenance.GetSwitchOSNames();100. 101. if(!switchOSNameCollectionResult.Result)102. {103. string formattedMessage = string.Format(104. "There was an error while communicating with the database. Error from the Database: [{0}]",105. switchOSNameCollectionResult.Message);106. Logging.LogMessage(formattedMessage, true);107. }108. else109. {110. SwitchOSNameCollection = switchOSNameCollectionResult.Payload;111. }112. 113. var testStatusCollectionResult = TransceiverToSwitchReporting.GetTransceiverSwitchQualificationListTestStatusNames();114. 115. if(!testStatusCollectionResult.Result)116. {117. string formattedMessage = string.Format(118. "There was an error while communicating with the database. Error from the Database: [{0}]",119. testStatusCollectionResult.Message);120. Logging.LogMessage(formattedMessage, true);121. }122. else123. {124. TestStatusCollection = testStatusCollectionResult.Payload;125. }126. 127. var qualificationListResult = TransceiverToSwitchReporting.GetTransceiverSwitchQualificationList();128. 129. if (!qualificationListResult.Result)130. {131. string formattedMessage = string.Format(132. "There was an error while communicating with the database. Error from the Database: [{0}]",133. qualificationListResult.Message);134. Logging.LogMessage(formattedMessage, true);135. }136. else137. {138. e.Result = qualificationListResult.Payload;139. }140. }141. 142. private void BackgroundWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)143. {144. Dispatcher.BeginInvoke(new Action<Collection<TransceiverSwitchQualificationListModel>>(RefreshQualificationListRadGridView), e.Result);145. }146. 147. private void DeleteRadButton_Click(object sender, System.Windows.RoutedEventArgs e)148. {149. // delete it from the database150. TransceiverSwitchQualificationListModel selectedItem = (TransceiverSwitchQualificationListModel)((RadButton)e.Source).DataContext;151. TransceiverToSwitchReporting.RemoveTransceiverSwitchQualificationListItem(selectedItem);152. 153. // delete it in the local cache154. ((ObservableCollection<TransceiverSwitchQualificationListModel>)QualificationListRadGridView.ItemsSource).Remove(selectedItem);155. }156. 157. private void ExportToExcelButton_Click(object sender, System.Windows.RoutedEventArgs e)158. {159. var dialog = new SaveFileDialog()160. {161. DefaultExt = "xlsx",162. Filter = String.Format("(*.{0})|*.{1}", "xlsx", "xlsx")163. };164. 165. if (dialog.ShowDialog() == true)166. {167. using (var stream = dialog.OpenFile())168. {169. QualificationListRadGridView.ExportToXlsx(stream);170. }171. }172. }173. 174. private void QualificationListRadGridView_Filtered(object sender, Telerik.Windows.Controls.GridView.GridViewFilteredEventArgs e)175. {176. if (e.ColumnFilterDescriptor.Column.UniqueName == "SwitchSupplierName")177. {178. Telerik.Windows.Controls.GridViewColumn switchOSColumn = QualificationListRadGridView.Columns["Switch.SwitchOS"];179. Telerik.Windows.Controls.GridView.IColumnFilterDescriptor switchOSFilterDescriptor = switchOSColumn.ColumnFilterDescriptor;180. 181. switchOSFilterDescriptor.SuspendNotifications();182. switchOSFilterDescriptor.DistinctFilter.Clear();183. 184. if (e.Added.Count<Telerik.Windows.Data.IFilterDescriptor>() > 0 || !string.IsNullOrEmpty((string)e.ColumnFilterDescriptor.FieldFilter.Filter1.Value))185. {186. Collection<string> suppliersToFilter = new Collection<string>();187. 188. foreach(Telerik.Windows.Data.OperatorValueFilterDescriptorBase addedItem in e.Added)189. {190. suppliersToFilter.Add((string)addedItem.Value);191. }192. 193. if(!string.IsNullOrEmpty((string)e.ColumnFilterDescriptor.FieldFilter.Filter1.Value.ToString()))194. {195. suppliersToFilter.Add((string)e.ColumnFilterDescriptor.FieldFilter.Filter1.Value);196. }197. 198. foreach (var qualificationListItem in (Collection<TransceiverSwitchQualificationListModel>)switchOSColumn.DataControl.ItemsSource)199. {200. string switchOSSupplierName = ((TransceiverSwitchQualificationListModel)qualificationListItem).SwitchOSSupplierName;201. 202. if (suppliersToFilter.Contains(switchOSSupplierName))// == (string)e.ColumnFilterDescriptor.FieldFilter.Filter1.Value)203. {204. switchOSFilterDescriptor.DistinctFilter.AddDistinctValue(((TransceiverSwitchQualificationListModel)qualificationListItem).SwitchOSName);205. }206. }207. }208. 209. switchOSFilterDescriptor.ResumeNotifications();210. }211. }212. 213. private void QualificationListRadGridView_RowEditEnded(object sender, GridViewRowEditEndedEventArgs e)214. {215. // update it in the database216. TransceiverSwitchQualificationListModel selectedItem = (TransceiverSwitchQualificationListModel)e.NewData;217. TransceiverToSwitchReporting.UpdateTransceiverSwitchQualificationListItem(selectedItem);218. }219. 220. private void RefreshQualificationListRadGridView(Collection<TransceiverSwitchQualificationListModel> qualificationList)221. {222. if (qualificationList != null)223. {224. LastUpdate = qualificationList.Select(ql => ql.LastUpdate).Max(ql => ql);225. QualificationListRadGridView.ItemsSource = new ObservableCollection<TransceiverSwitchQualificationListModel>(qualificationList);226. ((GridViewComboBoxColumn)QualificationListRadGridView.Columns["AssignedTo"]).ItemsSource = AssignedToCollection;227. ((GridViewComboBoxColumn)QualificationListRadGridView.Columns["SwitchOSName"]).ItemsSource = SwitchOSNameCollection;228. ((GridViewComboBoxColumn)QualificationListRadGridView.Columns["TestStatusName"]).ItemsSource = TestStatusCollection;229. }230. 231. QualificationListRadBusyIndicator.IsBusy = false;232. }233. 234. private void QualificationListRadGridView_Loaded(object sender, System.Windows.RoutedEventArgs e)235. {236. IsolatedStorageProvider storage = new IsolatedStorageProvider();237. storage.LoadFromStorage(new string[] { "QualificationListRadGridView" });238. }239. 240. private void QualificationListRadGridView_Unloaded(object sender, System.Windows.RoutedEventArgs e)241. {242. IsolatedStorageProvider storage = new IsolatedStorageProvider();243. storage.SaveToStorage(new string[] { "QualificationListRadGridView" });244. }245. }246.}
Any ideas on what could be going wrong? I attached some pictures to give a better idea of what I'm talking about... In the Before picture you can see I went to the Tab "Transceiver Switch Qualification List" and let it load. Then I re-ordered the orange Part # and Sup columns as shown in the ColumnReorder.png file...then I switched tabs away, then back to the Qualification List to find what you see in the After picture.
a little more info...persisting the resizing of columns seems to work just fine...just re-ordering them messes things up.
Also...the "Delete" buttons at the end disappear after being restored. Probably not directly related to the re-order issue...more than likely because it's a custom template and the IsolatedStorageProvider didn't know how to restore it...not that I know how to fix that, but that's my guess to what's going wrong. :)
We need more time to better check your scenario. We are going to contact you with more information about the case on the next business day.
Regards,
Dinko
Telerik
Please, excuse us for the delayed answer.
We are not sure what is the reason causing the GridView not to load his columns and the Delete button no to restore because some of the classes in the provided code snippets are missing. You can send us an isolated project from you application so we can further test it on our side.
Keep in mind that the order of the columns is not preserved out of the box by the PersistenceManager. In order to save the ordering, you will need to implement a CustomPropertyProvider for the . You can find such implementation in the GridViewSerialization SDK example.
Regards,
Dinko
Telerik
You were totally right. Once I created my own CustomPropertyProvider and pointed the PersistenceManager at it, the column order was preserved. Thanks for that.
I typed up the experience on my blog which points out where I was getting confused from the documentation. Please take a look to see if there's anything I misunderstood.
IsolatedStorageProvider v PersistenceManager: Dawn of Persistence
We are glad to see that you explained the PersistenceFramework basics in your blog. As we can see the information is convenient and it will be useful for the developers that read your blog. As a token of gratitude for the time spent for creating this blog post, we have updated your Telerik points.
Regards,
Dinko
Telerik
