AddValueChanged of dependency property descriptor results in memory leak as you already know. So, as described here, you can create custom class PropertyChangeNotifier to listen to any dependency property changes. This class takes advantage of the fact that bindings use weak references to manage associations so the class will not root the object who property changes it is watching. It also uses a WeakReference to maintain a reference to the object whose property it is watching without rooting that object. In this way, you can maintain a collection of these objects so that you can unhook the property change later without worrying about that collection rooting the object whose values you are watching. Complete implementation can be found here: http://agsmith.wordpress.com/2008/04/07/propertydescriptor-addvaluechanged-alternative/
Inheritance: System.Windows.DependencyObject, IDisposable
コード例 #1
0
        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);

            this.hwndSource = (HwndSource)PresentationSource.FromVisual(this);
            if (this.hwndSource == null)
            {
                return;
            }

            var ws   = this.hwndSource.Handle.GetWindowLong();
            var wsex = this.hwndSource.Handle.GetWindowLongEx();

            ws |= WS.POPUP;

            wsex &= ~WSEX.APPWINDOW;
            wsex |= WSEX.TOOLWINDOW;

            if (this._owner.ResizeMode == ResizeMode.NoResize || this._owner.ResizeMode == ResizeMode.CanMinimize)
            {
                wsex |= WSEX.TRANSPARENT;
            }

            this.hwndSource.Handle.SetWindowLong(ws);
            this.hwndSource.Handle.SetWindowLongEx(wsex);
            this.hwndSource.AddHook(this.WndProc);

            this.handle      = this.hwndSource.Handle;
            this.ownerHandle = new WindowInteropHelper(this._owner).Handle;

            this.resizeModeChangeNotifier = new PropertyChangeNotifier(this._owner, ResizeModeProperty);
            this.resizeModeChangeNotifier.ValueChanged += this.ResizeModeChanged;
        }
コード例 #2
0
        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
            this.hwndSource = (HwndSource)PresentationSource.FromVisual(this);
            if (this.hwndSource == null)
            {
                return;
            }
            WS   windowLong   = this.hwndSource.Handle.GetWindowLong();
            WSEX windowLongEx = this.hwndSource.Handle.GetWindowLongEx();

            windowLongEx ^= WSEX.APPWINDOW;
            windowLongEx |= WSEX.NOACTIVATE;
            if (base.Owner.ResizeMode == System.Windows.ResizeMode.NoResize || base.Owner.ResizeMode == System.Windows.ResizeMode.CanMinimize)
            {
                windowLongEx |= WSEX.TRANSPARENT;
            }
            this.hwndSource.Handle.SetWindowLong(windowLong);
            this.hwndSource.Handle.SetWindowLongEx(windowLongEx);
            this.hwndSource.AddHook(new HwndSourceHook(this.WndProc));
            this.handle      = this.hwndSource.Handle;
            this.ownerHandle = (new WindowInteropHelper(base.Owner)).Handle;
            this.resizeModeChangeNotifier = new PropertyChangeNotifier(base.Owner, Window.ResizeModeProperty);
            this.resizeModeChangeNotifier.ValueChanged += new EventHandler(this.ResizeModeChanged);
        }
コード例 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="HamburgerMenu"/> class.
        /// </summary>
        public HamburgerMenu()
        {
            this.DefaultStyleKey = typeof(HamburgerMenu);

            this.actualWidthPropertyChangeNotifier = new PropertyChangeNotifier(this, ActualWidthProperty);
            this.actualWidthPropertyChangeNotifier.ValueChanged += (s, e) => this.CoerceValue(OpenPaneLengthProperty);
        }
コード例 #4
0
        private void AttachVisibilityHandler(WindowCommandsItem container, UIElement item)
        {
            if (container != null)
            {
                if (null == item)
                {
                    // if item is not a UIElement then maybe the ItemsSource binds to a collection of objects
                    // and an ItemTemplate is set, so let's try to solve this
                    container.ApplyTemplate();
                    var content = container.ContentTemplate?.LoadContent() as UIElement;
                    if (null == content)
                    {
                        // no UIElement was found, so don't show this container
                        container.Visibility = Visibility.Collapsed;
                    }

                    return;
                }

                container.Visibility = item.Visibility;
                var isVisibilityNotifier = new PropertyChangeNotifier(item, VisibilityProperty);
                isVisibilityNotifier.ValueChanged         += this.VisibilityPropertyChanged;
                container.VisibilityPropertyChangeNotifier = isVisibilityNotifier;
            }
        }
コード例 #5
0
        private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PropertyChangeNotifier propertyChangeNotifier = (PropertyChangeNotifier)d;

            if (propertyChangeNotifier.ValueChanged != null)
            {
                propertyChangeNotifier.ValueChanged(propertyChangeNotifier.PropertySource, EventArgs.Empty);
            }
        }
コード例 #6
0
        private void AttachHandlers(Flyout flyout)
        {
            var isOpenNotifier = new PropertyChangeNotifier(flyout, Flyout.IsOpenProperty);
            isOpenNotifier.ValueChanged += FlyoutStatusChanged;
            flyout.IsOpenPropertyChangeNotifier = isOpenNotifier;

            var themeNotifier = new PropertyChangeNotifier(flyout, Flyout.ThemeProperty);
            themeNotifier.ValueChanged += FlyoutStatusChanged;
            flyout.ThemePropertyChangeNotifier = themeNotifier;
        }
コード例 #7
0
        private void AttachHandlers(Flyout flyout)
        {
            PropertyChangeNotifier propertyChangeNotifier = new PropertyChangeNotifier(flyout, Flyout.IsOpenProperty);

            propertyChangeNotifier.ValueChanged += new EventHandler(this.FlyoutStatusChanged);
            flyout.IsOpenPropertyChangeNotifier  = propertyChangeNotifier;
            PropertyChangeNotifier propertyChangeNotifier1 = new PropertyChangeNotifier(flyout, Flyout.ThemeProperty);

            propertyChangeNotifier1.ValueChanged += new EventHandler(this.FlyoutStatusChanged);
            flyout.ThemePropertyChangeNotifier    = propertyChangeNotifier1;
        }
コード例 #8
0
        private void AttachHandlers(Flyout flyout)
        {
            var isOpenNotifier = new PropertyChangeNotifier(flyout, Flyout.IsOpenProperty);

            isOpenNotifier.ValueChanged        += FlyoutStatusChanged;
            flyout.IsOpenPropertyChangeNotifier = isOpenNotifier;

            var themeNotifier = new PropertyChangeNotifier(flyout, Flyout.ThemeProperty);

            themeNotifier.ValueChanged        += FlyoutStatusChanged;
            flyout.ThemePropertyChangeNotifier = themeNotifier;
        }
コード例 #9
0
ファイル: WindowCommands.cs プロジェクト: yunxuan0123/Piggy2
 private void AttachVisibilityHandler(WindowCommandsItem container, UIElement item)
 {
     if (container != null)
     {
         if (item == null)
         {
             container.Visibility = System.Windows.Visibility.Collapsed;
             return;
         }
         container.Visibility = item.Visibility;
         PropertyChangeNotifier propertyChangeNotifier = new PropertyChangeNotifier(item, UIElement.VisibilityProperty);
         propertyChangeNotifier.ValueChanged       += new EventHandler(this.VisibilityPropertyChanged);
         container.VisibilityPropertyChangeNotifier = propertyChangeNotifier;
     }
 }
コード例 #10
0
ファイル: WindowCommands.cs プロジェクト: zsxgb/MahApps.Metro
        private void AttachVisibilityHandler(WindowCommandsItem container, UIElement item)
        {
            if (container != null)
            {
                // hide the container, if there is no UIElement
                if (null == item)
                {
                    container.Visibility = Visibility.Collapsed;
                    return;
                }

                container.Visibility = item.Visibility;
                var isVisibilityNotifier = new PropertyChangeNotifier(item, UIElement.VisibilityProperty);
                isVisibilityNotifier.ValueChanged         += VisibilityPropertyChanged;
                container.VisibilityPropertyChangeNotifier = isVisibilityNotifier;
            }
        }
コード例 #11
0
        private void AttachVisibilityHandler(WindowCommandsItem container, UIElement item)
        {
            if (container != null)
            {
                // hide the container, if there is no UIElement
                if (null == item)
                {
                    container.Visibility = Visibility.Collapsed;
                    return;
                }

                container.Visibility = item.Visibility;
                var isVisibilityNotifier = new PropertyChangeNotifier(item, UIElement.VisibilityProperty);
                isVisibilityNotifier.ValueChanged += VisibilityPropertyChanged;
                container.VisibilityPropertyChangeNotifier = isVisibilityNotifier;
            }
        }
コード例 #12
0
 public ToggleSwitchButton()
 {
     isCheckedPropertyChangeNotifier = new PropertyChangeNotifier(this, ToggleSwitchButton.IsCheckedProperty);
     isCheckedPropertyChangeNotifier.ValueChanged += IsCheckedPropertyChangeNotifierValueChanged;
 }
コード例 #13
0
        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);

            this.hwndSource = (HwndSource)PresentationSource.FromVisual(this);
            if (hwndSource == null) return;
            
            var ws = hwndSource.Handle.GetWindowLong();
            var wsex = hwndSource.Handle.GetWindowLongEx();

            //ws |= WS.POPUP;
            wsex ^= WSEX.APPWINDOW;
            wsex |= WSEX.NOACTIVATE;
            if (this.Owner.ResizeMode == ResizeMode.NoResize || this.Owner.ResizeMode == ResizeMode.CanMinimize)
            {
                wsex |= WSEX.TRANSPARENT;
            }

            hwndSource.Handle.SetWindowLong(ws);
            hwndSource.Handle.SetWindowLongEx(wsex);
            hwndSource.AddHook(WndProc);

            handle = hwndSource.Handle;
            ownerHandle = new WindowInteropHelper(Owner).Handle;

            this.resizeModeChangeNotifier = new PropertyChangeNotifier(this.Owner, Window.ResizeModeProperty);
            this.resizeModeChangeNotifier.ValueChanged += ResizeModeChanged;
        }
コード例 #14
0
 public ToggleSwitchButton()
 {
     isCheckedPropertyChangeNotifier = new PropertyChangeNotifier(this, ToggleSwitchButton.IsCheckedProperty);
     isCheckedPropertyChangeNotifier.ValueChanged += IsCheckedPropertyChangeNotifierValueChanged;
 }
コード例 #15
0
        private void AttachVisibilityHandler(WindowCommandsItem container, UIElement item)
        {
            if (container != null)
            {
                if (null == item)
                {
                    // if item is not a UIElement then maybe the ItemsSource binds to a collection of objects
                    // and an ItemTemplate is set, so let's try to solve this
                    container.ApplyTemplate();
                    var content = container.ContentTemplate?.LoadContent() as UIElement;
                    if (null == content)
                    {
                        // no UIElement was found, so don't show this container
                        container.Visibility = Visibility.Collapsed;
                    }
                    return;
                }

                container.Visibility = item.Visibility;
                var isVisibilityNotifier = new PropertyChangeNotifier(item, UIElement.VisibilityProperty);
                isVisibilityNotifier.ValueChanged += VisibilityPropertyChanged;
                container.VisibilityPropertyChangeNotifier = isVisibilityNotifier;
            }
        }