Click here to Skip to main content
15,891,253 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
See more:
Hello,
I'm new to wpf..

-> In Windows Forms any Control or UserControl added to the Form
can be removed and destroyed from the Form calling .Dispose();

-> The question is how to do similar operation on Wpf Controls, even
on my own UserControls ?

Thank's!
Posted
Comments
Sergey Alexandrovich Kryukov 4-Oct-12 15:30pm    
Who told you you would need it?
--SA

Not true: this Dispose have nothing to do with removing anything from a form or anything like this.

And what do you thing Dispose(/* without paramters */)ystem.IDisposable.Dispose. Please read about this interface:
http://msdn.microsoft.com/en-us/library/system.idisposable.aspx[^].

You only need to disposing something which implements this interface. If this interface is not implemented (not in the base types list), there is nothing to "dispose". (Well, there are methods called Dispose not related to this interface. I'm not talking about them; and WPF UI elements have none of them.)

Background:

In .NET, the managed memory is reclaimed using the Garbage Collector (GC) eventually, for the objects that becomes unreachable. Normally, the users do not have any control on the destruction and reclaiming memory. But unmanaged memory needs to be reclaimed explicitly. The System.IDisposable.Dispose is usually used for this, but this is not the only use of this interface and this method — it can be anything, whatever you implement. You can implement this interface by any of your own classes or structures. The library System.Windows.Forms uses this mechanism, because it is based on legacy Windows API, thus using umnamaged memory.

In contrast, WPF does not need to use such outdated API. In fact, it have very little to do with Windows API, as most of WPF uses DirectX, well— directly; and DirectX is a multi-platform technology supported by hardware/firmware, not just by OS. So, the library code is free from disposing (but I'm not sure if it is 100% free; I never searched for that, which would be easy; anyway, I just explain in principle, why UI elements are not disposable: no need).

—SA
 
Share this answer
 
Comments
F. Aro 4-Oct-12 15:36pm    
aha i understand the process!
so what i need is to remove controls recently added dynamicaly to wpf window,
i need something like ..Children.Remove(?);
it's not logical to use visibility .. hidden
Sergey Alexandrovich Kryukov 4-Oct-12 16:29pm    
And adding/removing has nothing to do with visibility. A hidden UI element is still in the tree.
There are logical and visual trees. Please see:
http://msdn.microsoft.com/en-us/library/ms753391.aspx.
--SA
F. Aro 4-Oct-12 15:45pm    
any solution ?
Sergey Alexandrovich Kryukov 4-Oct-12 16:23pm    
Yes, exactly:
Control someControl = //...
Control someParentControl = //...
//...
someParentControl.Childred.Remove(someControl);

--SA
Sergey Alexandrovich Kryukov 4-Oct-12 16:28pm    
And for your understanding, there is no "dynamically" vs. "statically". Everything is done equally "dynamically" If you mean having controls in XAML, they are still created/added during runtime exactly as you would do it with the code. And actually such code does exist, only it is auto-generated (just based on XAML, which is just data); and you can find this code if your search directories under the directory of location of the project files. Those files are auto-generated (as the result of build), appears in the file-system directory, but just not shown in the project tree of the Solution Explorer. Only "true" source files are there, not auto-generated.
--SA
You can use WeakEventManager + IWeakEventListener to Remove EventHandler of Control before Remove Control. Else can Leak Memory
Finally call GC.

Note: Sample only to reference, when use Event 'click' in WeakListternImp, it must a Action or delegate
Sample here: You can reference:
WeakEvent Any Event

file:MainWindow.cs
// Author: Ledangkhoa
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;

namespace WpfApplication9
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(MainWindow_Loaded);
        }

        void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            var lis = new WeakListternImp{Name = "Click"};
            WeakImp.AddHandle(button1, lis);

            var lisc = new WeakListternImp { Name = "Checked" };
            WeakImp.AddHandle(checkBox1, lisc);
            var lis2 = new WeakListternImp { Name = "PreviewMouseDoubleClick" };
            WeakImp.AddHandle(button2, lis2);
        }
    }

    class WeakImp : WeakEventManager
    {
       static Dictionary<object,WeakListternImp> hold = null;
       static Dictionary<object, Delegate> dele = null;
        
        internal static void AddHandle(object source, IWeakEventListener handler)
        {
            if (hold == null)
            {
                hold = new Dictionary<object,WeakListternImp>();
                
            }
            hold.Add(source, handler as WeakListternImp);
            Current.ProtectedAddListener(source, handler);

        }
        internal static void RemoveHandle(object source, IWeakEventListener handler)
        {
            Current.ProtectedRemoveListener(source, handler);
        }

        public static WeakImp Current
        {
            get
            {
                WeakImp man = GetCurrentManager(typeof(WeakImp)) as WeakImp;
                if (man == null)
                {
                    man = new WeakImp();
                    SetCurrentManager(typeof(WeakImp), man);
                }
                return man;
            }
        }

        protected override void StartListening(object source)
        {
            Type ty = source.GetType();
            var t = from x in source.GetType().GetEvents();
                    where x.Name == hold[source].Name
                    select x;

            MethodInfo meinf = this.GetType().GetMethod("Active",BindingFlags.Instance| BindingFlags.NonPublic);

            Type typehandler = t.First().EventHandlerType;

            EventInfo eventinfo = t.First();
            if (dele==null)
            {
                dele = new Dictionary<object, Delegate>();
            }
            dele.Add(source,Delegate.CreateDelegate(typehandler,this,meinf));
            eventinfo.AddEventHandler(source, dele[source]);
        }

        void Active(object s, System.EventArgs e)
        {
            DeliverEvent(s, e);
        }


        protected override void StopListening(object source)
        {
            Type ty = source.GetType();
            var t = from x in source.GetType().GetEvents();
                    where x.Name == hold[source].Name
                    select x;

            MethodInfo meinf = this.GetType().GetMethod("Active", BindingFlags.Instance | BindingFlags.NonPublic);

            Type typehandler = t.First().EventHandlerType;

            EventInfo eventinfo = t.First();
            eventinfo.RemoveEventHandler(source, dele[source]);
            hold.Remove(source);
            dele.Remove(source);
            if (hold.Count == 0)
            {
                hold = null;
            }
            if (dele.Count == 0)
            {
                dele = null;
            }
            GC.Collect();
        }
    }
    class WeakListternImp : IWeakEventListener
    {
        public string Name { get; set; }
        public void click(object o, EventArgs e)
        {
            MessageBox.Show(o.ToString()+Name);
            If(Name == "Click")
                WeakImp.RemoveHandle(o, this);

        }
        public bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e)
        {
            click(sender, e);
            
            return true;
        }
    }
}


file:MainWindow.xaml
<window x:class="WpfApplication9.MainWindow" xmlns:x="#unknown">
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<grid>
<button content="click on" height="23" horizontalalignment="Left" margin="112,41,0,0" name="button1" verticalalignment="Top" width="75" />
<checkbox content="check on" height="16" horizontalalignment="Left" margin="116,115,0,0" name="checkBox1" verticalalignment="Top">
<button content="double click on" height="23" horizontalalignment="Left" margin="328,70,0,0" name="button2" verticalalignment="Top" width="120" />


Hope useful with you!
 
Share this answer
 
v7
Comments
F. Aro 4-Oct-12 17:09pm    
That was not what i was searching for,
anyway thank you, i may use something like this later!
You need to remove from the parent but also know what the parent is.

For example

C#
((Grid)customControl.Parent).Children.Remove(customControl);


If you do not know the parent type you can do some visual tree climbing. That is more complicated though.
 
Share this answer
 
v3
Comments
F. Aro 4-Oct-12 16:00pm    
Okay it's soved! Thank's
[no name] 4-Oct-12 16:03pm    
You are welcome :-)
Anas Karm. 11-Aug-14 1:57am    
That's worked. Simple, easy and efficient solution.

Thanks.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900