diff --git a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs
index 2da23f68084..da7a300324d 100644
--- a/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs
+++ b/src/DynamoCoreWpf/ViewModels/PackageManager/PackageManagerSearchViewModel.cs
@@ -304,8 +304,12 @@ public string SearchText
get { return _SearchText; }
set
{
- _SearchText = value;
- RaisePropertyChanged("SearchText");
+ if(_SearchText != value)
+ {
+ _SearchText = value;
+ SearchAndUpdateResults();
+ RaisePropertyChanged("SearchText");
+ }
}
}
@@ -1073,19 +1077,24 @@ public bool TimedOut
}
}
+ private System.Timers.Timer aTimer;
+
private void StartTimer()
{
- var aTimer = new System.Timers.Timer();
- aTimer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
+ if(aTimer == null)
+ aTimer = new System.Timers.Timer();
+
+ aTimer.Elapsed += OnTimedEvent;
aTimer.Interval = MAX_LOAD_TIME;
aTimer.AutoReset = false;
aTimer.Enabled = true;
+ aTimer.Start();
}
private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
var aTimer = (System.Timers.Timer)sender;
- aTimer.Dispose();
+ aTimer.Stop();
// If we have managed to get all the results
// Simply dispose of the timer
@@ -1577,12 +1586,23 @@ public void DisableSearchTextBox()
///
/// Clear after closing down
///
- internal void Close()
+ internal void PackageManagerViewClose()
+ {
+ SearchAndUpdateResults(String.Empty); // reset the search text property
+ InitialResultsLoaded = false;
+ TimedOut = false;
+ }
+
+ ///
+ /// Remove PackageManagerSearchViewModel resources
+ ///
+ internal void Dispose()
{
+ nonHostFilter?.ForEach(f => f.PropertyChanged -= filter_PropertyChanged);
+ aTimer.Elapsed -= OnTimedEvent;
+
TimedOut = false; // reset the timedout screen
InitialResultsLoaded = false; // reset the loading screen settings
- RequestShowFileDialog -= OnRequestShowFileDialog;
- nonHostFilter.ForEach(f => f.PropertyChanged -= filter_PropertyChanged);
ClearMySearchResults();
}
diff --git a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs
index 571626f7efa..ccdd8a491ce 100644
--- a/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs
+++ b/src/DynamoCoreWpf/Views/Core/DynamoView.xaml.cs
@@ -2014,6 +2014,7 @@ private void WindowClosed(object sender, EventArgs e)
this.Dispose();
sharedViewExtensionLoadedParams?.Dispose();
+ this._pkgSearchVM?.Dispose();
}
// the key press event is being intercepted before it can get to
@@ -2274,9 +2275,11 @@ private void DynamoViewModelRequestShowPackageManager(object s, EventArgs e)
{
packageManagerWindow.Navigate((e as OpenPackageManagerEventArgs).Tab);
}
+
_pkgSearchVM.RefreshAndSearchAsync();
}
+
internal void EnableEnvironment(bool isEnabled)
{
this.mainGrid.IsEnabled = isEnabled;
diff --git a/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerSearchControl.xaml b/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerSearchControl.xaml
index c4b7ced2d6b..93968bc06db 100644
--- a/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerSearchControl.xaml
+++ b/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerSearchControl.xaml
@@ -335,7 +335,8 @@
+ Margin="0 5 0 0"
+ IsEnabled="{Binding Path=InitialResultsLoaded, UpdateSourceTrigger=PropertyChanged}" />
@@ -387,18 +388,16 @@
Visibility="{Binding IsAnyFilterOn, Converter={StaticResource BoolToVisibilityCollapsedConverter}, UpdateSourceTrigger=PropertyChanged}" />
-
-
+ Visibility="Visible" />
-
+
diff --git a/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerSearchControl.xaml.cs b/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerSearchControl.xaml.cs
index 4e9422310d3..44101cca15d 100644
--- a/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerSearchControl.xaml.cs
+++ b/src/DynamoCoreWpf/Views/PackageManager/Controls/PackageManagerSearchControl.xaml.cs
@@ -2,6 +2,7 @@
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
+using Dynamo.Controls;
using Dynamo.PackageManager.ViewModels;
namespace Dynamo.PackageManager.UI
@@ -23,6 +24,18 @@ public PackageManagerSearchControl()
private void InitializeContext(object sender, RoutedEventArgs e)
{
PkgSearchVM = this.DataContext as PackageManagerSearchViewModel;
+
+ if (PkgSearchVM != null)
+ {
+ // Create the binding once the DataContext is available
+ var binding = new Binding(nameof(PackageManagerSearchViewModel.InitialResultsLoaded))
+ {
+ Source = PkgSearchVM,
+ Converter = new InverseBooleanToVisibilityCollapsedConverter()
+ };
+
+ this.loadingAnimationSearchControlScreen.SetBinding(UIElement.VisibilityProperty, binding);
+ }
}
diff --git a/src/DynamoCoreWpf/Views/PackageManager/Controls/SearchBoxControl.xaml b/src/DynamoCoreWpf/Views/PackageManager/Controls/SearchBoxControl.xaml
index f1e3f9110a1..155ec0f6c20 100644
--- a/src/DynamoCoreWpf/Views/PackageManager/Controls/SearchBoxControl.xaml
+++ b/src/DynamoCoreWpf/Views/PackageManager/Controls/SearchBoxControl.xaml
@@ -115,9 +115,8 @@
Cursor="IBeam"
HorizontalAlignment="Stretch"
IsEnabled="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Path=IsEnabled}"
- TextChanged="SearchTextBox_OnTextChanged"
- IsKeyboardFocusWithinChanged="SearchTextBox_OnKeyboardFocusWithinChanged"
- Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}">
+ Text="{Binding SearchText, Delay=100, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
+ IsKeyboardFocusWithinChanged="SearchTextBox_OnKeyboardFocusWithinChanged">
diff --git a/src/DynamoCoreWpf/Views/PackageManager/Controls/SearchBoxControl.xaml.cs b/src/DynamoCoreWpf/Views/PackageManager/Controls/SearchBoxControl.xaml.cs
index 051d87833ea..96cb033f590 100644
--- a/src/DynamoCoreWpf/Views/PackageManager/Controls/SearchBoxControl.xaml.cs
+++ b/src/DynamoCoreWpf/Views/PackageManager/Controls/SearchBoxControl.xaml.cs
@@ -1,11 +1,8 @@
-using Dynamo.PackageManager;
-using HelixToolkit.Wpf.SharpDX;
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
-using System.Windows.Threading;
namespace Dynamo.PackageManager.UI
{
@@ -15,10 +12,6 @@ namespace Dynamo.PackageManager.UI
///
public partial class SearchBoxControl : UserControl
{
- private DispatcherTimer delayTimer;
-
- // set delay for event 500ms
- private static int delayTime = 500;
///
/// Constructor
///
@@ -26,37 +19,7 @@ public SearchBoxControl()
{
InitializeComponent();
}
- private static DispatcherTimer Debounce(DispatcherTimer dispatcher, TimeSpan interval, Action action)
- {
- dispatcher?.Stop();
- dispatcher = null;
- dispatcher = new DispatcherTimer(interval, DispatcherPriority.ApplicationIdle, (s, e) =>
- {
- dispatcher?.Stop();
- action.Invoke();
- }, Dispatcher.CurrentDispatcher);
- dispatcher?.Start();
-
- return dispatcher;
- }
-
- ///
- /// Handles Search Box Text Changed Event
- ///
- ///
- ///
- ///
- private void SearchTextBox_OnTextChanged(object sender, TextChangedEventArgs e)
- {
- Debounce(delayTimer, TimeSpan.FromMilliseconds(delayTime), () =>
- {
- var textBox = sender as TextBox;
- if (textBox == null) return;
- (this.DataContext as PackageManagerSearchViewModel)?.SearchAndUpdateResults(textBox.Text);
- textBox.Focus();
- });
- }
private void OnSearchClearButtonClicked(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
this.SearchTextBox.Clear();
@@ -78,86 +41,6 @@ private void SearchTextBox_OnKeyboardFocusWithinChanged(object sender, Dependenc
}
}
- ///
- /// A multivalue visibilty converter
- /// value 0 - boolean
- /// value 1 - text
- ///
- public class MultiBooleanToVisibilityConverter : IMultiValueConverter
- {
- public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
- {
- bool focusVisible = true;
- bool textVisible = true;
-
- foreach (object value in values)
- {
- if (value is bool)
- {
- if ((bool)value)
- {
- focusVisible = false; // If the textbox has the focus, don't show the Control..
- }
- else
- {
- focusVisible = true; // If the textbox don't have focus, we can show the Control..
- }
- }
- else
- {
- if (value != null && string.IsNullOrWhiteSpace(value.ToString()))
- {
- textVisible = true; // If the textbox has no text, we can show the Control..
- }
- else
- {
- textVisible = false; // If the textbox has some text, don't show the Control..
- }
- }
- }
-
- // Only of both conditions are true, show the Control..
- if (focusVisible && textVisible)
- return Visibility.Visible;
- else
- return Visibility.Collapsed;
- }
-
- public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
-
- ///
- /// Converts null or empty string to Visibility Collapsed
- ///
- public class NonEmptyStringToCollapsedConverter : IValueConverter
- {
- enum Parameters
- {
- Normal, Inverted
- }
-
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- parameter = parameter ?? "Normal";
-
- var boolValue = value is string s && !string.IsNullOrEmpty(s);
- var direction = (Parameters)Enum.Parse(typeof(Parameters), (string)parameter);
-
- if (direction == Parameters.Inverted)
- return !boolValue ? Visibility.Visible : Visibility.Collapsed;
-
- return boolValue ? Visibility.Visible : Visibility.Collapsed;
- }
-
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- return null;
- }
- }
-
///
/// Converts null or empty string to Visibility Collapsed
///
diff --git a/src/DynamoCoreWpf/Views/PackageManager/PackageManagerView.xaml.cs b/src/DynamoCoreWpf/Views/PackageManager/PackageManagerView.xaml.cs
index 3ce63bbd82f..1e6dab884ac 100644
--- a/src/DynamoCoreWpf/Views/PackageManager/PackageManagerView.xaml.cs
+++ b/src/DynamoCoreWpf/Views/PackageManager/PackageManagerView.xaml.cs
@@ -6,6 +6,7 @@
using Dynamo.Controls;
using Dynamo.Logging;
using Dynamo.UI;
+using Dynamo.Utilities;
using Dynamo.ViewModels;
using Dynamo.Wpf.Utilities;
using DynamoUtilities;
@@ -124,7 +125,7 @@ private void WindowClosed(object sender, EventArgs e)
{
this.packageManagerPublish.Dispose();
this.PackageManagerViewModel.PackageSearchViewModel.RequestShowFileDialog -= OnRequestShowFileDialog;
- this.PackageManagerViewModel.PackageSearchViewModel.Close();
+ this.PackageManagerViewModel.PackageSearchViewModel.PackageManagerViewClose();
}
private void SearchForPackagesButton_Click(object sender, RoutedEventArgs e)
diff --git a/test/DynamoCoreWpfTests/PackageManager/PackageManagerUITests.cs b/test/DynamoCoreWpfTests/PackageManager/PackageManagerUITests.cs
index 987a2ecc1fd..64bd688ff23 100644
--- a/test/DynamoCoreWpfTests/PackageManager/PackageManagerUITests.cs
+++ b/test/DynamoCoreWpfTests/PackageManager/PackageManagerUITests.cs
@@ -1613,6 +1613,33 @@ public void PackageManagerClosesWithDynamo()
AssertWindowClosedWithDynamoView();
}
+ [Test]
+ public void SearchBoxInactiveOnWindowOpened()
+ {
+ ViewModel.OnRequestPackageManagerDialog(null, null);
+
+ var windows = GetWindowEnumerable(View.OwnedWindows);
+ var packageManagerView = windows.First(x => x is PackageManagerView) as PackageManagerView;
+
+ Assert.IsNotNull(packageManagerView);
+
+ var searchBox = LogicalTreeHelper.FindLogicalNode(packageManagerView, "SearchBox") as UserControl;
+ Assert.IsNotNull(searchBox);
+ Assert.IsFalse(searchBox.IsEnabled);
+
+ packageManagerView.PackageManagerViewModel.PackageSearchViewModel.InitialResultsLoaded = true;
+ Assert.IsTrue(searchBox.IsEnabled);
+ }
+
+ [Test]
+ public void PackageManagerDialogDoesNotThrowExceptions()
+ {
+ Assert.DoesNotThrow(() => ViewModel.OnRequestPackageManagerDialog(null, null), "Package Manager View did not open without exceptions");
+
+ AssertWindowOwnedByDynamoView();
+ }
+
+
///
/// Asserts that the filter context menu will stay open while the user interacts with it
///