diff --git a/src/CalcViewModel/Common/DelegateCommand.h b/src/CalcViewModel/Common/DelegateCommand.h index 3a341287e..6dbb49ccf 100644 --- a/src/CalcViewModel/Common/DelegateCommand.h +++ b/src/CalcViewModel/Common/DelegateCommand.h @@ -7,18 +7,14 @@ namespace CalculatorApp { namespace Common { - template - ref class DelegateCommand : public Windows::UI::Xaml::Input::ICommand - { - internal : - - typedef void (TTarget::*CommandHandlerFunc)(Platform::Object ^); + public delegate void DelegateCommandHandler(Platform::Object ^ parameter); - DelegateCommand(TTarget ^ target, CommandHandlerFunc func) - : m_weakTarget(target) - , m_function(func) - { - } + public ref class DelegateCommand sealed : public Windows::UI::Xaml::Input::ICommand + { + public: + DelegateCommand(DelegateCommandHandler ^ handler) + : m_handler(handler) + {} private: // Explicit, and private, implementation of ICommand, this way of programming makes it so @@ -27,11 +23,7 @@ namespace CalculatorApp // code in the app calling Execute. virtual void ExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::Execute { - TTarget ^ target = m_weakTarget.Resolve(); - if (target) - { - (target->*m_function)(parameter); - } + m_handler->Invoke(parameter); } virtual bool CanExecuteImpl(Platform::Object ^ parameter) sealed = Windows::UI::Xaml::Input::ICommand::CanExecute @@ -39,9 +31,9 @@ namespace CalculatorApp return true; } - virtual event Windows::Foundation::EventHandler^ CanExecuteChangedImpl + virtual event Windows::Foundation::EventHandler ^ CanExecuteChangedImpl { - virtual Windows::Foundation::EventRegistrationToken add(Windows::Foundation::EventHandler^ handler) sealed = Windows::UI::Xaml::Input::ICommand::CanExecuteChanged::add + virtual Windows::Foundation::EventRegistrationToken add(Windows::Foundation::EventHandler ^ handler) sealed = Windows::UI::Xaml::Input::ICommand::CanExecuteChanged::add { return m_canExecuteChanged += handler; } @@ -52,17 +44,25 @@ namespace CalculatorApp } private: + DelegateCommandHandler ^ m_handler; - event Windows::Foundation::EventHandler^ m_canExecuteChanged; - - CommandHandlerFunc m_function; - Platform::WeakReference m_weakTarget; + event Windows::Foundation::EventHandler ^ m_canExecuteChanged; }; template - DelegateCommand ^ MakeDelegate(TTarget ^ target, TFuncPtr&& function) { - return ref new DelegateCommand(target, std::forward(function)); - } - + DelegateCommandHandler ^ MakeDelegateCommandHandler(TTarget ^ target, TFuncPtr&& function) + { + Platform::WeakReference weakTarget(target); + return ref new DelegateCommandHandler([weakTarget, function=std::forward(function)](Platform::Object ^ param) + { + TTarget ^ thatTarget = weakTarget.Resolve(); + if (nullptr != thatTarget) + { + (thatTarget->*function)(param); + } + } + ); + } } } + diff --git a/src/CalcViewModel/Common/Utils.h b/src/CalcViewModel/Common/Utils.h index fe13e7638..36a65b857 100644 --- a/src/CalcViewModel/Common/Utils.h +++ b/src/CalcViewModel/Common/Utils.h @@ -168,11 +168,22 @@ public: // The variable member generated by this macro should not be used in the class code, use the // property getter instead. #define COMMAND_FOR_METHOD(p, m) \ - property Windows::UI::Xaml::Input::ICommand^ p {\ - Windows::UI::Xaml::Input::ICommand^ get() {\ - if (!donotuse_##p) {\ - donotuse_##p = CalculatorApp::Common::MakeDelegate(this, &m);\ - } return donotuse_##p; }} private: Windows::UI::Xaml::Input::ICommand^ donotuse_##p; \ + property Windows::UI::Xaml::Input::ICommand ^ p \ + { \ + Windows::UI::Xaml::Input::ICommand ^ get() \ + { \ + if (!donotuse_##p) \ + { \ + donotuse_##p = ref new CalculatorApp::Common::DelegateCommand( \ + CalculatorApp::Common::MakeDelegateCommandHandler(this, &m) \ + ); \ + } \ + return donotuse_##p; \ + } \ + } \ + \ +private: \ + Windows::UI::Xaml::Input::ICommand ^ donotuse_##p; \ \ public: diff --git a/src/Calculator/Calculator.csproj b/src/Calculator/Calculator.csproj index cf88e7c25..458004abf 100644 --- a/src/Calculator/Calculator.csproj +++ b/src/Calculator/Calculator.csproj @@ -151,11 +151,11 @@ - EquationStylePanelControl.xaml + Calculator.xaml diff --git a/src/Calculator/DelegateCommand.cs b/src/Calculator/DelegateCommand.cs deleted file mode 100644 index 14094b97a..000000000 --- a/src/Calculator/DelegateCommand.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; - -namespace CalculatorApp.Common -{ - internal class DelegateCommand : System.Windows.Input.ICommand - { - public delegate void CommandHandlerFunc(object obj); - - public DelegateCommand(TTarget target, CommandHandlerFunc func) - { - m_weakTarget = new WeakReference(target); - m_function = func; - } - - public event EventHandler CanExecuteChanged; - - public bool CanExecute(object parameter) - { - return true; - } - - public void Execute(object parameter) - { - object target = m_weakTarget.Target; - if (target != null && target is TTarget) - { - m_function(parameter); - } - } - - private CommandHandlerFunc m_function; - private WeakReference m_weakTarget; - } -} - diff --git a/src/Calculator/Utils/DelegateCommandUtils.cs b/src/Calculator/Utils/DelegateCommandUtils.cs new file mode 100644 index 000000000..562b1c5e0 --- /dev/null +++ b/src/Calculator/Utils/DelegateCommandUtils.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using CalculatorApp.Common; + +namespace CalculatorApp.Utils +{ + static class DelegateCommandUtils + { + public static DelegateCommand MakeDelegateCommand(TTarget target, DelegateCommandHandler handler) + where TTarget : class + { + WeakReference weakTarget = new WeakReference(target); + return new DelegateCommand(param => + { + TTarget thatTarget = weakTarget.Target as TTarget; + if(null != thatTarget) + { + handler.Invoke(param); + } + }); + } + } +} + diff --git a/src/Calculator/Views/Calculator.xaml.cs b/src/Calculator/Views/Calculator.xaml.cs index dfcdf2967..58a5f2a99 100644 --- a/src/Calculator/Views/Calculator.xaml.cs +++ b/src/Calculator/Views/Calculator.xaml.cs @@ -9,6 +9,7 @@ using CalculatorApp.Common; using CalculatorApp.Converters; using CalculatorApp.Controls; +using CalculatorApp.Utils; using CalculatorApp.ViewModel; using Windows.Foundation; @@ -140,7 +141,7 @@ public System.Windows.Input.ICommand HistoryButtonPressed { if (donotuse_HistoryButtonPressed == null) { - donotuse_HistoryButtonPressed = new DelegateCommand(this, ToggleHistoryFlyout); + donotuse_HistoryButtonPressed = DelegateCommandUtils.MakeDelegateCommand(this, ToggleHistoryFlyout); } return donotuse_HistoryButtonPressed; } diff --git a/src/Calculator/Views/CalculatorScientificAngleButtons.xaml.cs b/src/Calculator/Views/CalculatorScientificAngleButtons.xaml.cs index bee6445d7..8c3c3f9ca 100644 --- a/src/Calculator/Views/CalculatorScientificAngleButtons.xaml.cs +++ b/src/Calculator/Views/CalculatorScientificAngleButtons.xaml.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using System.Diagnostics; using CalculatorApp; +using CalculatorApp.Utils; using CalculatorApp.ViewModel; using Windows.Foundation; @@ -47,7 +48,7 @@ public System.Windows.Input.ICommand ButtonPressed { if (donotuse_ButtonPressed == null) { - donotuse_ButtonPressed = new CalculatorApp.Common.DelegateCommand(this, OnAngleButtonPressed); + donotuse_ButtonPressed = DelegateCommandUtils.MakeDelegateCommand(this, OnAngleButtonPressed); } return donotuse_ButtonPressed; } diff --git a/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cs b/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cs index 9cd536719..f345ae497 100644 --- a/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cs +++ b/src/Calculator/Views/GraphingCalculator/GraphingCalculator.xaml.cs @@ -9,6 +9,7 @@ using CalculatorApp.Common; using CalculatorApp.Common.Automation; using CalculatorApp.Controls; +using CalculatorApp.Utils; using CalculatorApp.ViewModel; //using CalcManager.NumberFormattingUtils; using GraphControl; @@ -114,7 +115,7 @@ public System.Windows.Input.ICommand ZoomOutButtonPressed { if (donotuse_ZoomOutButtonPressed == null) { - donotuse_ZoomOutButtonPressed = new DelegateCommand(this, OnZoomOutCommand); + donotuse_ZoomOutButtonPressed = DelegateCommandUtils.MakeDelegateCommand(this, OnZoomOutCommand); } return donotuse_ZoomOutButtonPressed; } @@ -127,7 +128,7 @@ public System.Windows.Input.ICommand ZoomInButtonPressed { if (donotuse_ZoomInButtonPressed == null) { - donotuse_ZoomInButtonPressed = new DelegateCommand(this, OnZoomInCommand); + donotuse_ZoomInButtonPressed = DelegateCommandUtils.MakeDelegateCommand(this, OnZoomInCommand); } return donotuse_ZoomInButtonPressed; } diff --git a/src/Calculator/Views/StateTriggers/CalculatorProgrammerDisplayPanel.xaml.cs b/src/Calculator/Views/StateTriggers/CalculatorProgrammerDisplayPanel.xaml.cs index 34276f98b..6c7deb5d2 100644 --- a/src/Calculator/Views/StateTriggers/CalculatorProgrammerDisplayPanel.xaml.cs +++ b/src/Calculator/Views/StateTriggers/CalculatorProgrammerDisplayPanel.xaml.cs @@ -2,6 +2,7 @@ using System.Windows.Input; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; +using CalculatorApp.Utils; // The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 @@ -16,8 +17,7 @@ public ICommand BitLengthButtonPressed { if (donotuse_BitLengthButtonPressed == null) { - donotuse_BitLengthButtonPressed = - new Common.DelegateCommand(this, OnBitLengthButtonPressed); + donotuse_BitLengthButtonPressed = DelegateCommandUtils.MakeDelegateCommand(this, OnBitLengthButtonPressed); } return donotuse_BitLengthButtonPressed; }