11using System ;
2- using System . Diagnostics ;
2+ using System . Threading . Tasks ;
33using System . Windows ;
44using System . Windows . Controls ;
55using System . Windows . Input ;
@@ -16,7 +16,7 @@ namespace WPFDevelopers.Controls
1616 [ TemplatePart ( Name = GridTemplateName , Type = typeof ( SmallPanel ) ) ]
1717 [ TemplatePart ( Name = ReplaceButtonTemplateName , Type = typeof ( Button ) ) ]
1818 [ TemplatePart ( Name = AddButtonTemplateName , Type = typeof ( Button ) ) ]
19- public class CropAvatar : Control
19+ public class CropAvatar : Control , IDisposable
2020 {
2121 private const string CanvasTemplateName = "PART_Canvas" ;
2222 private const string ImageTemplateName = "PART_Image" ;
@@ -33,6 +33,8 @@ public class CropAvatar : Control
3333 private BitmapFrame _bitmapFrame ;
3434 private Canvas _canvas ;
3535 private CroppedBitmap _crop ;
36+ private WriteableBitmap _cachedResult ;
37+ private bool _disposed = false ;
3638 private SmallPanel _grid ;
3739 private Image _image ;
3840 private int _initialX , _initialY , _voffsetX , _voffsetY ;
@@ -91,8 +93,15 @@ public override void OnApplyTemplate()
9193 _addButton . Click -= OnAddButton_Click ;
9294 _addButton . Click += OnAddButton_Click ;
9395 }
96+ Unloaded -= OnCropAvatar_Unloaded ;
97+ Unloaded += OnCropAvatar_Unloaded ;
9498 }
9599
100+ private void OnCropAvatar_Unloaded ( object sender , RoutedEventArgs e )
101+ {
102+ Dispose ( ) ;
103+ }
104+
96105 private void OnCanvas_Loaded ( object sender , RoutedEventArgs e )
97106 {
98107 if ( sender is Canvas canvas )
@@ -190,15 +199,31 @@ private void OnAddButton_Click(object sender, RoutedEventArgs e)
190199
191200 private void InitialImage ( )
192201 {
202+ CleanupOldResources ( ) ;
193203 _vNewStartX = 0 ;
194204 _vNewStartY = 0 ;
195205 var uri = Helper . ImageUri ( ) ;
196206 if ( uri == null ) return ;
197- var bitmap = new BitmapImage ( ) ;
198- bitmap . BeginInit ( ) ;
199- bitmap . CacheOption = BitmapCacheOption . OnLoad ;
200- bitmap . UriSource = uri ;
201- bitmap . EndInit ( ) ;
207+ BitmapImage bitmap = null ;
208+ try
209+ {
210+ bitmap = new BitmapImage ( ) ;
211+ bitmap . BeginInit ( ) ;
212+ bitmap . CacheOption = BitmapCacheOption . OnLoad ;
213+ bitmap . UriSource = uri ;
214+ bitmap . EndInit ( ) ;
215+ if ( bitmap . CanFreeze )
216+ bitmap . Freeze ( ) ;
217+ }
218+ catch
219+ {
220+ throw ;
221+ }
222+
223+ if ( bitmap == null || bitmap . Width == 0 || bitmap . Height == 0 )
224+ {
225+ return ;
226+ }
202227 if ( bitmap . Height > bitmap . Width )
203228 {
204229 var scale = bitmap . Width / _path . Width ;
@@ -253,5 +278,79 @@ private void InitialImage()
253278 }
254279 OutImageSource = _crop ;
255280 }
281+
282+ private void CleanupOldResources ( )
283+ {
284+ if ( _bitmapFrame != null )
285+ {
286+ _bitmapFrame = null ;
287+ }
288+
289+ if ( _crop != null )
290+ {
291+ _crop = null ;
292+ }
293+
294+ #if NET40
295+ Task . Factory . StartNew ( ( ) =>
296+ {
297+ GC . Collect ( 2 ) ;
298+ } ) ;
299+ #else
300+ Task . Run ( ( ) =>
301+ {
302+ GC . Collect ( 2 , GCCollectionMode . Forced ) ;
303+ } ) ;
304+ #endif
305+ }
306+
307+ public void Dispose ( )
308+ {
309+ Dispose ( true ) ;
310+ GC . SuppressFinalize ( this ) ;
311+ }
312+
313+ protected virtual void Dispose ( bool disposing )
314+ {
315+ if ( ! _disposed )
316+ {
317+ if ( disposing )
318+ {
319+ CleanupOldResources ( ) ;
320+
321+ if ( _image != null )
322+ {
323+ _image . Source = null ;
324+ }
325+ if ( _canvas != null )
326+ {
327+ _canvas . Loaded -= OnCanvas_Loaded ;
328+ }
329+ if ( _image != null )
330+ {
331+ _image . MouseDown -= OnImage_MouseDown ;
332+ _image . MouseMove -= OnImage_MouseMove ;
333+ _image . MouseUp -= OnImage_MouseUp ;
334+ _image . MouseLeave -= OnImage_MouseLeave ;
335+ }
336+ if ( _replaceButton != null )
337+ {
338+ _replaceButton . Click -= OnReplaceButton_Click ;
339+ }
340+ if ( _addButton != null )
341+ {
342+ _addButton . Click -= OnAddButton_Click ;
343+ }
344+ Unloaded -= OnCropAvatar_Unloaded ;
345+ }
346+ _disposed = true ;
347+ }
348+ }
349+
350+
351+ ~ CropAvatar ( )
352+ {
353+ Dispose ( false ) ;
354+ }
256355 }
257356}
0 commit comments