From 466b54210bc5066e6e29107d6c8f996f360b1426 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Thu, 5 Jul 2018 19:24:36 +0300 Subject: Done some work on color catalog. Removed manipulation enabled from everywhere! Implemented "DelayCommand for TouchButton".. --- .../MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt index 5ae51fc02..a8100d53a 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt @@ -1 +1 @@ -Thu 07/05/2018 16:44:59.08 +Thu 07/05/2018 18:36:01.68 -- cgit v1.3.1 From 4ca8cee91fb46977b75e8329c18d9b6a4654b12e Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Sat, 7 Jul 2018 15:02:20 +0300 Subject: Working on PPC jobs loading performance... --- Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 1572864 -> 1572864 bytes .../Tango.MachineStudio.UI/Resources/BuildDate.txt | 2 +- .../Native/Tango.ColorLib/Tango.ColorLib.vcxproj | 2 +- .../Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs | 23 ++- .../Tango.PPC.Jobs/ViewModels/JobsViewVM.cs | 2 +- .../PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml | 2 +- .../Modules/Tango.PPC.Jobs/Views/JobView.xaml.cs | 8 +- .../Controls/AsyncAdornerControl.cs | 205 +++++++++++++++++++++ .../ExtensionMethods/IListExtensions.cs | 26 +++ .../ObservableCollectionExtensions.cs | 53 ++++++ .../Notifications/INotificationProvider.cs | 21 +++ .../PPC/Tango.PPC.Common/Tango.PPC.Common.csproj | 5 + .../Controls/HeaderLoadingControl.xaml | 16 ++ .../Controls/HeaderLoadingControl.xaml.cs | 28 +++ .../Notifications/DefaultNotificationProvider.cs | 35 ++++ .../PPC/Tango.PPC.UI/Tango.PPC.UI.csproj | 8 + .../PPC/Tango.PPC.UI/Views/LayoutView.xaml | 24 +++ .../Tango.BL/EntitiesExtensions/BrushStop.cs | 64 ++++--- .../Components/FrameworkElementSerializer.cs | 124 +++++++++++++ .../Visual_Studio/Tango.Core/ExtendedObject.cs | 10 + .../Visual_Studio/Tango.Core/Tango.Core.csproj | 1 + .../Tango.SharedUI/Controls/NavigationControl.cs | 2 +- .../Converters/SegmentLengthToWidthConverter.cs | 4 +- .../Tango.Touch/Controls/TouchListBox.xaml | 2 +- 25 files changed, 625 insertions(+), 42 deletions(-) create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/AsyncAdornerControl.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/ExtensionMethods/IListExtensions.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.Common/ExtensionMethods/ObservableCollectionExtensions.cs create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/HeaderLoadingControl.xaml create mode 100644 Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/HeaderLoadingControl.xaml.cs create mode 100644 Software/Visual_Studio/Tango.Core/Components/FrameworkElementSerializer.cs (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index f83f0de4f..33d333496 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index b4729c4ef..18972bbe8 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt index a8100d53a..f5ca2ed87 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt @@ -1 +1 @@ -Thu 07/05/2018 18:36:01.68 +Sat 07/07/2018 1:27:31.31 diff --git a/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj b/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj index 506745a12..bed1cc7bb 100644 --- a/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj +++ b/Software/Visual_Studio/Native/Tango.ColorLib/Tango.ColorLib.vcxproj @@ -23,7 +23,7 @@ {625B2A26-97A9-45C9-8BCF-6BD30F593E17} Win32Proj TangoColorLib - 10.0.15063.0 + 10.0.16299.0 diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs index a22e1fdf4..52f2b8f6e 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs @@ -419,13 +419,28 @@ namespace Tango.PPC.Jobs.ViewModels SpoolTypes = await _db.SpoolTypes.ToListAsync(); Customers = await _db.Customers.Where(x => x.OrganizationGuid == ApplicationManager.Machine.OrganizationGuid).ToListAsync(); - if (!_check_gamut_thread.IsAlive) - { - _check_gamut_thread.Start(); - } + //if (!_check_gamut_thread.IsAlive) + //{ + // _check_gamut_thread.Start(); + //} + + //Job.Segments.ReloadAsyncIdle((current, total) => + //{ + + // NotificationProvider.SetGlobalBusyMessage(String.Format("Loading job segment {0}/{1}...", current, total)); + + //}, () => + //{ + + //}); SegmentsCollectionView = CollectionViewSource.GetDefaultView(Job.Segments); SegmentsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Segment.SegmentIndex), ListSortDirection.Ascending)); + + InvokeUIOnIdle(() => + { + NotificationProvider.ReleaseGlobalBusyMessage(); + }); } #endregion diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs index 699744d5a..1275248eb 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs @@ -202,7 +202,7 @@ namespace Tango.PPC.Jobs.ViewModels /// The job. public async void SelectJob(Job job) { - await Task.Delay(300); + NotificationProvider.SetGlobalBusyMessage("Loading job..."); await NavigationManager.NavigateTo(nameof(JobSummeryView)); RaiseMessage(new JobSelectedMessage() { Job = job }); } diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml index a55e5a7d3..0ac903b1d 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml @@ -70,7 +70,7 @@ - + diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml.cs index c3e3ab688..1e6ef30ed 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml.cs @@ -12,17 +12,23 @@ using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; +using static Tango.SharedUI.Controls.NavigationControl; namespace Tango.PPC.Jobs.Views { /// /// Interaction logic for JobView.xaml /// - public partial class JobView : UserControl + public partial class JobView : UserControl ,INavigationView { public JobView() { InitializeComponent(); } + + public void OnNavigated() + { + scrollViewer.ScrollToTop(); + } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/AsyncAdornerControl.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/AsyncAdornerControl.cs new file mode 100644 index 000000000..b20e93ff9 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/AsyncAdornerControl.cs @@ -0,0 +1,205 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Interop; +using System.Windows.Markup; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Tango.Core.Components; + +namespace Tango.PPC.Common.Controls +{ + public partial class AsyncAdornerControl : ContentControl + { + private bool _loaded; + + public enum GWL + { + ExStyle = -20 + } + + public enum WS_EX + { + Transparent = 0x20, + Layered = 0x80000 + } + + public enum LWA + { + ColorKey = 0x1, + Alpha = 0x2 + } + + [DllImport("user32.dll", EntryPoint = "GetWindowLong")] + public static extern int GetWindowLong(IntPtr hWnd, GWL nIndex); + + [DllImport("user32.dll", EntryPoint = "SetWindowLong")] + public static extern int SetWindowLong(IntPtr hWnd, GWL nIndex, int dwNewLong); + + [DllImport("user32.dll", EntryPoint = "SetLayeredWindowAttributes")] + public static extern bool SetLayeredWindowAttributes(IntPtr hWnd, int crKey, byte alpha, LWA dwFlags); + + private Window _window; + + public AsyncAdornerControl() + { + Loaded += AsyncAdornerControl_Loaded; + LayoutUpdated += AsyncAdornerControl_LayoutUpdated; + IsVisibleChanged += AsyncAdornerControl_IsVisibleChanged; + } + + private void AsyncAdornerControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) + { + if (Visibility == Visibility.Visible) + { + ShowWindow(); + } + else + { + HideWindow(); + } + } + + private void AsyncAdornerControl_LayoutUpdated(object sender, EventArgs e) + { + SyncBounds(); + } + + public Type ViewType + { + get { return (Type)GetValue(ViewTypeProperty); } + set { SetValue(ViewTypeProperty, value); } + } + public static readonly DependencyProperty ViewTypeProperty = + DependencyProperty.Register("ViewType", typeof(Type), typeof(AsyncAdornerControl), new PropertyMetadata(null)); + + protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) + { + base.OnRenderSizeChanged(sizeInfo); + SyncBounds(); + } + + private void AsyncAdornerControl_Loaded(object sender, RoutedEventArgs e) + { + if (!this.IsInDesignMode()) + { + if (_loaded) return; + + _loaded = true; + + var handle = new WindowInteropHelper(System.Windows.Application.Current.MainWindow).Handle; + + System.Windows.Application.Current.MainWindow.LocationChanged += MainWindow_LocationChanged; + + Visibility v = Visibility; + Type type = ViewType; + + var xaml = FrameworkElementSerializer.Serialize(Content as FrameworkElement); + object dc = this.DataContext; + Content = null; + + Thread thread = new Thread(() => + { + _window = new Window(); + _window.WindowStyle = WindowStyle.None; + _window.ResizeMode = ResizeMode.NoResize; + _window.ShowInTaskbar = false; + _window.AllowsTransparency = true; + _window.Background = Brushes.Transparent; + _window.WindowStartupLocation = WindowStartupLocation.Manual; + SyncBounds(); + + if (v != Visibility.Visible) + { + _window.Opacity = 0; + } + + new WindowInteropHelper(_window).Owner = handle; + + _window.ShowActivated = false; + + //FrameworkElement element = Activator.CreateInstance(type) as FrameworkElement; + + var cloned = FrameworkElementSerializer.Deserialize(xaml); + cloned.DataContext = dc; + + _window.Content = cloned; + + _window.Show(); + + int wl = GetWindowLong(handle, GWL.ExStyle); + wl = wl | 0x80000 | 0x20; + SetWindowLong(handle, GWL.ExStyle, wl); + SetLayeredWindowAttributes(handle, 0, 128, LWA.Alpha); + + SyncBounds(); + + System.Windows.Threading.Dispatcher.Run(); + }); + + thread.SetApartmentState(ApartmentState.STA); + thread.IsBackground = true; + thread.Start(); + } + } + + private void MainWindow_LocationChanged(object sender, EventArgs e) + { + SyncBounds(); + } + + private void SyncBounds() + { + if (_window != null) + { + this.BeginInvoke(() => + { + Point location = PointToScreen(new Point(0, 0)); + Size size = new Size(ActualWidth, ActualHeight); + + _window.BeginInvoke(() => + { + _window.Top = location.Y; + _window.Left = location.X; + _window.Width = size.Width; + _window.Height = size.Height; + }); + }); + } + } + + private void HideWindow() + { + if (_window != null) + { + _window.BeginInvoke(() => + { + _window.Hide(); + }); + } + } + + private void ShowWindow() + { + if (_window != null) + { + _window.BeginInvoke(() => + { + _window.Opacity = 1; + _window.Show(); + }); + } + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/ExtensionMethods/IListExtensions.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/ExtensionMethods/IListExtensions.cs new file mode 100644 index 000000000..fdf07ccff --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/ExtensionMethods/IListExtensions.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Threading; + +public static class IListExtensions +{ + public static IList ToListAsyncIdle(this IList source) + { + var copy = source.ToList(); + IList result = new List(); + + foreach (var item in copy) + { + Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + result.Add(item); + }), DispatcherPriority.ContextIdle); + } + + return result; + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/ExtensionMethods/ObservableCollectionExtensions.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/ExtensionMethods/ObservableCollectionExtensions.cs new file mode 100644 index 000000000..c539273d9 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/ExtensionMethods/ObservableCollectionExtensions.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Threading; + +public static class ObservableCollectionExtensions +{ + public static ObservableCollection ToObservableCollectionAsyncIdle(this ObservableCollection source) + { + var copy = source.ToList(); + ObservableCollection result = new ObservableCollection(); + + foreach (var item in copy) + { + Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + result.Add(item); + }), DispatcherPriority.ContextIdle); + } + + return result; + } + + public static void ReloadAsyncIdle(this ObservableCollection source, Action onProgress, Action onComplete = null) + { + var copy = source.ToList(); + source.Clear(); + + int count = copy.Count; + int completed = 0; + + foreach (var item in copy) + { + Application.Current.Dispatcher.BeginInvoke(new Action(() => + { + source.Add(item); + completed++; + + onProgress?.Invoke(completed, count); + + if (completed == count) + { + onComplete?.Invoke(); + } + }), DispatcherPriority.ContextIdle); + } + } +} + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/INotificationProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/INotificationProvider.cs index 96de08447..f7fb67a19 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/INotificationProvider.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notifications/INotificationProvider.cs @@ -128,5 +128,26 @@ namespace Tango.PPC.Common.Notifications /// Gets the pop notification command. /// RelayCommand PopNotificationCommand { get; } + + /// + /// Gets a value indicating whether this instance is in global busy state. + /// + bool IsInGlobalBusyState { get; } + + /// + /// Sets the global busy message. + /// + /// The message. + void SetGlobalBusyMessage(String message); + + /// + /// Releases the global busy message. + /// + void ReleaseGlobalBusyMessage(); + + /// + /// Gets the current global busy message. + /// + String GlobalBusyMessage { get; } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj index 98210a76f..192658560 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj @@ -75,6 +75,8 @@ ..\..\packages\System.Data.SQLite.Linq.1.0.108.0\lib\net46\System.Data.SQLite.Linq.dll True + + @@ -92,9 +94,12 @@ PPC.cs + TwineCatalogControl.xaml + + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/HeaderLoadingControl.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/HeaderLoadingControl.xaml new file mode 100644 index 000000000..5b07e1fa2 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/HeaderLoadingControl.xaml @@ -0,0 +1,16 @@ + + + + + Loading... + + + diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/HeaderLoadingControl.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/HeaderLoadingControl.xaml.cs new file mode 100644 index 000000000..540e829c9 --- /dev/null +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Controls/HeaderLoadingControl.xaml.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +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; + +namespace Tango.PPC.UI.Controls +{ + /// + /// Interaction logic for HeaderLoadingControl.xaml + /// + public partial class HeaderLoadingControl : UserControl + { + public HeaderLoadingControl() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/DefaultNotificationProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/DefaultNotificationProvider.cs index ae777839b..aaa5a9cf3 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/DefaultNotificationProvider.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Notifications/DefaultNotificationProvider.cs @@ -386,5 +386,40 @@ namespace Tango.PPC.UI.Notifications { return ShowDialog(Activator.CreateInstance()); } + + /// + /// Sets the global busy message. + /// + /// The message. + public void SetGlobalBusyMessage(string message) + { + GlobalBusyMessage = message; + IsInGlobalBusyState = true; + + RaisePropertyChanged(nameof(IsInGlobalBusyState)); + RaisePropertyChanged(nameof(GlobalBusyMessage)); + } + + /// + /// Releases the global busy message. + /// + public void ReleaseGlobalBusyMessage() + { + GlobalBusyMessage = null; + IsInGlobalBusyState = false; + + RaisePropertyChanged(nameof(IsInGlobalBusyState)); + RaisePropertyChanged(nameof(GlobalBusyMessage)); + } + + /// + /// Gets the current global busy message. + /// + public string GlobalBusyMessage { get; private set; } + + /// + /// Gets a value indicating whether this instance is in global busy state. + /// + public bool IsInGlobalBusyState { get; private set; } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj index d2763510a..eaf53b993 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj @@ -101,6 +101,7 @@ + @@ -111,6 +112,9 @@ PPC.cs + + HeaderLoadingControl.xaml + @@ -140,6 +144,10 @@ MainView.xaml + + Designer + MSBuild:Compile + MSBuild:Compile Designer diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml index c7d019981..7d170d04f 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml +++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml @@ -4,12 +4,14 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Tango.PPC.UI.Views" + xmlns:localControls="clr-namespace:Tango.PPC.UI.Controls" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:fa="http://schemas.fontawesome.io/icons/" xmlns:vm="clr-namespace:Tango.PPC.UI.ViewModels" xmlns:global="clr-namespace:Tango.PPC.UI" xmlns:localConverters="clr-namespace:Tango.PPC.UI.Converters" xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch" + xmlns:commonControls="clr-namespace:Tango.PPC.Common.Controls;assembly=Tango.PPC.Common" xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" xmlns:keyboard="clr-namespace:Tango.Touch.Keyboard;assembly=Tango.Touch" mc:Ignorable="d" @@ -110,6 +112,28 @@ + + + + + + + + + + + diff --git a/Software/Visual_Studio/Tango.BL/EntitiesExtensions/BrushStop.cs b/Software/Visual_Studio/Tango.BL/EntitiesExtensions/BrushStop.cs index fad528bea..352437c34 100644 --- a/Software/Visual_Studio/Tango.BL/EntitiesExtensions/BrushStop.cs +++ b/Software/Visual_Studio/Tango.BL/EntitiesExtensions/BrushStop.cs @@ -16,6 +16,7 @@ using Tango.PMR.ColorLab; using Google.Protobuf; using System.Runtime.InteropServices; using Tango.PMR; +using System.Diagnostics; namespace Tango.BL.Entities { @@ -302,41 +303,44 @@ namespace Tango.BL.Entities /// private void SynchronizeColorSpaces() { - Rgb rgb = new Rgb(Red, Green, Blue); - Cmyk cmyk = new Cmyk(Cyan, Magenta, Yellow, Black); - Lab lab = new Lab(L, A, B); - - switch ((ColorSpaces)ColorSpace.Code) + Task.Factory.StartNew(() => { - case ColorSpaces.RGB: - cmyk = rgb.To(); - lab = rgb.To(); - break; - case ColorSpaces.CMYK: - rgb = cmyk.To(); - lab = cmyk.To(); - break; - case ColorSpaces.LAB: - rgb = lab.To(); - cmyk = lab.To(); - break; - } + Rgb rgb = new Rgb(Red, Green, Blue); + Cmyk cmyk = new Cmyk(Cyan, Magenta, Yellow, Black); + Lab lab = new Lab(L, A, B); + + switch ((ColorSpaces)ColorSpace.Code) + { + case ColorSpaces.RGB: + cmyk = rgb.To(); + lab = rgb.To(); + break; + case ColorSpaces.CMYK: + rgb = cmyk.To(); + lab = cmyk.To(); + break; + case ColorSpaces.LAB: + rgb = lab.To(); + cmyk = lab.To(); + break; + } - _red = (int)rgb.R; - _green = (int)rgb.G; - _blue = (int)rgb.B; + _red = (int)rgb.R; + _green = (int)rgb.G; + _blue = (int)rgb.B; - _cyan = cmyk.C; - _magenta = cmyk.M; - _yellow = cmyk.Y; - _black = cmyk.K; + _cyan = cmyk.C; + _magenta = cmyk.M; + _yellow = cmyk.Y; + _black = cmyk.K; - _l = lab.L; - _a = lab.A; - _b = lab.B; + _l = lab.L; + _a = lab.A; + _b = lab.B; - //TODO: Remove this.. - IsOutOfGamut = _red > 250; + //TODO: Remove this.. + IsOutOfGamut = _red > 250; + }); } #endregion diff --git a/Software/Visual_Studio/Tango.Core/Components/FrameworkElementSerializer.cs b/Software/Visual_Studio/Tango.Core/Components/FrameworkElementSerializer.cs new file mode 100644 index 000000000..8f0c6a266 --- /dev/null +++ b/Software/Visual_Studio/Tango.Core/Components/FrameworkElementSerializer.cs @@ -0,0 +1,124 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Data; +using System.Windows.Markup; +using System.Xml; + +namespace Tango.Core.Components +{ + public static class FrameworkElementSerializer + { + private class BindingConvertor : ExpressionConverter + { + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + if (destinationType == typeof(MarkupExtension)) + return true; + else return false; + } + public override object ConvertTo(ITypeDescriptorContext context, + System.Globalization.CultureInfo culture, + object value, Type destinationType) + { + if (destinationType == typeof(MarkupExtension)) + { + BindingExpression bindingExpression = value as BindingExpression; + if (bindingExpression == null) + throw new Exception(); + return bindingExpression.ParentBinding; + } + + return base.ConvertTo(context, culture, value, destinationType); + } + + public static void Register() + { + Attribute[] attr = new Attribute[1]; + TypeConverterAttribute vConv = new TypeConverterAttribute(typeof(TC)); + attr[0] = vConv; + TypeDescriptor.AddAttributes(typeof(T), attr); + } + } + + static FrameworkElementSerializer() + { + BindingConvertor.Register(); + } + + /// + /// Clones the specified element. + /// + /// The element. + /// + public static FrameworkElement Clone(FrameworkElement element) + { + var sb = new StringBuilder(); + var writer = XmlWriter.Create(sb, new XmlWriterSettings + { + Indent = true, + ConformanceLevel = ConformanceLevel.Fragment, + OmitXmlDeclaration = true, + NamespaceHandling = NamespaceHandling.OmitDuplicates, + }); + var mgr = new XamlDesignerSerializationManager(writer); + + // HERE BE MAGIC!!! + mgr.XamlWriterMode = XamlWriterMode.Expression; + // THERE WERE MAGIC!!! + + XamlWriter.Save(element, mgr); + String xaml = sb.ToString(); + + StringReader stringReader = new StringReader(xaml); + XmlReader xmlReader = XmlReader.Create(stringReader); + FrameworkElement cloned = (FrameworkElement)XamlReader.Load(xmlReader) as FrameworkElement; + return cloned; + } + + /// + /// Serializes the specified element. + /// + /// The element. + /// + public static String Serialize(FrameworkElement element) + { + var sb = new StringBuilder(); + var writer = XmlWriter.Create(sb, new XmlWriterSettings + { + Indent = true, + ConformanceLevel = ConformanceLevel.Fragment, + OmitXmlDeclaration = true, + NamespaceHandling = NamespaceHandling.OmitDuplicates, + }); + var mgr = new XamlDesignerSerializationManager(writer); + + // HERE BE MAGIC!!! + mgr.XamlWriterMode = XamlWriterMode.Expression; + // THERE WERE MAGIC!!! + + XamlWriter.Save(element, mgr); + String xaml = sb.ToString(); + + return xaml; + } + + /// + /// Deserializes the specified xaml. + /// + /// The xaml. + /// + public static FrameworkElement Deserialize(String xaml) + { + StringReader stringReader = new StringReader(xaml); + XmlReader xmlReader = XmlReader.Create(stringReader); + FrameworkElement cloned = (FrameworkElement)XamlReader.Load(xmlReader) as FrameworkElement; + return cloned; + } + } +} diff --git a/Software/Visual_Studio/Tango.Core/ExtendedObject.cs b/Software/Visual_Studio/Tango.Core/ExtendedObject.cs index 30179c3bf..cafafef4f 100644 --- a/Software/Visual_Studio/Tango.Core/ExtendedObject.cs +++ b/Software/Visual_Studio/Tango.Core/ExtendedObject.cs @@ -8,6 +8,7 @@ using System.Runtime.CompilerServices; using System.Text; using System.Threading.Tasks; using System.Windows; +using System.Windows.Threading; using Tango.Core.Commands; using Tango.Core.IO; using Tango.Logging; @@ -111,6 +112,15 @@ namespace Tango.Core Application.Current.Dispatcher.BeginInvoke(action); } + /// + /// Invokes the specified action on the UI Thread when context is idle. + /// + /// The action. + protected virtual void InvokeUIOnIdle(Action action) + { + Application.Current.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle); + } + /// /// Invokes the specified action on the UI Thread. /// diff --git a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj index 7523fe7e5..864f4f797 100644 --- a/Software/Visual_Studio/Tango.Core/Tango.Core.csproj +++ b/Software/Visual_Studio/Tango.Core/Tango.Core.csproj @@ -62,6 +62,7 @@ Core.cs + diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs b/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs index aae75532c..2b59bb663 100644 --- a/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs +++ b/Software/Visual_Studio/Tango.SharedUI/Controls/NavigationControl.cs @@ -222,7 +222,7 @@ namespace Tango.SharedUI.Controls #region Attached Properties - #region Draggable + #region NavigationName /// /// Determines the element navigation name. diff --git a/Software/Visual_Studio/Tango.SharedUI/Converters/SegmentLengthToWidthConverter.cs b/Software/Visual_Studio/Tango.SharedUI/Converters/SegmentLengthToWidthConverter.cs index 64699e053..e3d5db01d 100644 --- a/Software/Visual_Studio/Tango.SharedUI/Converters/SegmentLengthToWidthConverter.cs +++ b/Software/Visual_Studio/Tango.SharedUI/Converters/SegmentLengthToWidthConverter.cs @@ -27,7 +27,9 @@ namespace Tango.SharedUI.Converters double segmentLength = System.Convert.ToDouble(values[3]); double totalLength = job.Length; - return (segmentLength / totalLength) * elementWidth; + double result = (segmentLength / totalLength) * elementWidth; + + return double.IsInfinity(result) ? 0d : result; } else { diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchListBox.xaml b/Software/Visual_Studio/Tango.Touch/Controls/TouchListBox.xaml index 92279d5e6..61342fc0b 100644 --- a/Software/Visual_Studio/Tango.Touch/Controls/TouchListBox.xaml +++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchListBox.xaml @@ -40,7 +40,7 @@ - + -- cgit v1.3.1 From f4688d6113dc33deac114bd6999967fec246b8c0 Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Sun, 8 Jul 2018 09:07:39 +0300 Subject: Working on PPC segments loading performance. --- Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 1572864 -> 1572864 bytes .../Tango.MachineStudio.UI/Resources/BuildDate.txt | 2 +- .../Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs | 71 +++++++++++++-------- .../Tango.PPC.Jobs/ViewModels/JobsViewVM.cs | 1 - .../Tango.BL/EntitiesExtensions/BrushStop.cs | 52 +++++++++++---- .../Tango.BL/EntitiesExtensions/Job.cs | 24 ++++++- .../Tango.BL/EntitiesExtensions/Segment.cs | 55 ++++++++-------- .../Tango.Touch/Controls/TouchNumericTextBox.cs | 13 +++- 9 files changed, 147 insertions(+), 71 deletions(-) (limited to 'Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI') diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index 33d333496..6c0e0cf74 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index 18972bbe8..4d6ecff99 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt index f5ca2ed87..0d0ef0a18 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/Resources/BuildDate.txt @@ -1 +1 @@ -Sat 07/07/2018 1:27:31.31 +Sun 07/08/2018 0:25:00.31 diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs index 52f2b8f6e..260670e08 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs @@ -34,6 +34,7 @@ namespace Tango.PPC.Jobs.ViewModels private ObservablesContext _db; private bool _can_navigate_back; private Thread _check_gamut_thread; + private Job _job_to_load; #region Properties @@ -405,15 +406,40 @@ namespace Tango.PPC.Jobs.ViewModels /// Handles the job selected message. /// /// The message. - private async void HandleJobSelectedMessage(JobSelectedMessage message) + private void HandleJobSelectedMessage(JobSelectedMessage message) { + _job_to_load = message.Job; + } + + #endregion + + #region IPPC ViewModel Overrides + + /// + /// Called when the application has been started. + /// + public override void OnApplicationStarted() + { + + } + + /// + /// Called when the navigation system has navigated to this VM view. + /// + public async override void OnNavigatedTo() + { + NotificationProvider.SetGlobalBusyMessage("Loading job details..."); + + _can_navigate_back = false; + base.OnNavigatedTo(); + if (_db != null) { _db.Dispose(); } _db = ObservablesContext.CreateDefault(); - Job = await _db.Jobs.SingleOrDefaultAsync(x => x.Guid == message.Job.Guid); + Job = await _db.Jobs.SingleOrDefaultAsync(x => x.Guid == _job_to_load.Guid); Rmls = await _db.Rmls.ToListAsync(); ColorSpaces = await _db.ColorSpaces.ToListAsync(); SpoolTypes = await _db.SpoolTypes.ToListAsync(); @@ -437,42 +463,33 @@ namespace Tango.PPC.Jobs.ViewModels SegmentsCollectionView = CollectionViewSource.GetDefaultView(Job.Segments); SegmentsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Segment.SegmentIndex), ListSortDirection.Ascending)); - InvokeUIOnIdle(() => + InvokeUIOnIdle(() => { NotificationProvider.ReleaseGlobalBusyMessage(); }); } - #endregion - - #region IPPC ViewModel Overrides - - /// - /// Called when the application has been started. - /// - public override void OnApplicationStarted() - { - - } - - /// - /// Called when the navigation system has navigated to this VM view. - /// - public override void OnNavigatedTo() - { - _can_navigate_back = false; - base.OnNavigatedTo(); - } - /// /// Called before the navigation system navigates from this object. /// Return false to abort the navigation. /// /// - public override Task OnNavigateOutRequest() + public async override Task OnNavigateOutRequest() { - if (_can_navigate_back) return Task.FromResult(true); - return NotificationProvider.ShowQuestion("Are you sure you want to exit this job?"); + bool result = true; + + if (!_can_navigate_back) + { + result = await NotificationProvider.ShowQuestion("Are you sure you want to exit this job?"); + } + + if (result) + { + Job = null; + SegmentsCollectionView = null; + } + + return result; } #endregion diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs index 1275248eb..d2c229187 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs @@ -202,7 +202,6 @@ namespace Tango.PPC.Jobs.ViewModels /// The job. public async void SelectJob(Job job) { - NotificationProvider.SetGlobalBusyMessage("Loading job..."); await NavigationManager.NavigateTo(nameof(JobSummeryView)); RaiseMessage(new JobSelectedMessage() { Job = job }); } diff --git a/Software/Visual_Studio/Tango.BL/EntitiesExtensions/BrushStop.cs b/Software/Visual_Studio/Tango.BL/EntitiesExtensions/BrushStop.cs index 352437c34..fa5dc4acb 100644 --- a/Software/Visual_Studio/Tango.BL/EntitiesExtensions/BrushStop.cs +++ b/Software/Visual_Studio/Tango.BL/EntitiesExtensions/BrushStop.cs @@ -26,14 +26,34 @@ namespace Tango.BL.Entities /// public partial class BrushStop { - [DllImport("Tango.ColorLib.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "Convert")] - public static extern int Convert(IntPtr data, int size, ref IntPtr output); - [NotMapped] private bool _ignorePropChanged; + private static List _colorPropertyNames; + + static BrushStop() + { + _colorPropertyNames = new List(); + + _colorPropertyNames.Add(nameof(Red)); + _colorPropertyNames.Add(nameof(Green)); + _colorPropertyNames.Add(nameof(Blue)); + + _colorPropertyNames.Add(nameof(L)); + _colorPropertyNames.Add(nameof(A)); + _colorPropertyNames.Add(nameof(B)); + + _colorPropertyNames.Add(nameof(Cyan)); + _colorPropertyNames.Add(nameof(Magenta)); + _colorPropertyNames.Add(nameof(Yellow)); + _colorPropertyNames.Add(nameof(Black)); + + _colorPropertyNames.Add(nameof(Color)); + } + #region Properties + private ObservableCollection _liquidVolumes; /// /// Gets or sets the collection of this brush stop liquid volumes. @@ -172,6 +192,7 @@ namespace Tango.BL.Entities if (Segment != null) { OffsetPercent = (value / Segment.Length) * 100d; + RaisePropertyChangedAuto(); } } } @@ -261,22 +282,31 @@ namespace Tango.BL.Entities if (!_ignorePropChanged && propName != nameof(ColorSpace) && ColorSpace != null) { + if (_colorPropertyNames.Contains(propName)) + { + SynchronizeColorSpaces(); - SynchronizeColorSpaces(); + _ignorePropChanged = true; - _ignorePropChanged = true; + foreach (var prop in _colorPropertyNames) + { + RaisePropertyChanged(prop); + } - foreach (var prop in typeof(BrushStop).GetProperties(BindingFlags.Instance | BindingFlags.Public)) - { - RaisePropertyChanged(prop.Name); - } + if (Segment != null) + { + Segment.RaiseSegmentBrushChanged(); + } + _ignorePropChanged = false; + } + } + if (propName == nameof(OffsetPercent)) + { if (Segment != null) { Segment.RaiseSegmentBrushChanged(); } - - _ignorePropChanged = false; } } diff --git a/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Job.cs b/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Job.cs index 52f123f7a..68cd371fd 100644 --- a/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Job.cs +++ b/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Job.cs @@ -20,6 +20,8 @@ namespace Tango.BL.Entities /// public partial class Job { + private double _lastLength; + /// /// Initializes a new instance of the class. /// @@ -46,7 +48,11 @@ namespace Tango.BL.Entities [JsonIgnore] public double Length { - get { return Segments.Sum(x => x.Length) + (EnableInterSegment ? (InterSegmentLength * (Segments.Count > 0 ? Segments.Count - 1 : Segments.Count)) : 0); } + get + { + _lastLength = GetLength(); + return _lastLength; + } } /// @@ -183,8 +189,11 @@ namespace Tango.BL.Entities /// protected virtual void OnLengthChanged() { - RaisePropertyChanged(nameof(Length)); - LengthChanged?.Invoke(this, new EventArgs()); + if (_lastLength != GetLength()) + { + RaisePropertyChanged(nameof(Length)); + LengthChanged?.Invoke(this, new EventArgs()); + } } #endregion @@ -255,6 +264,15 @@ namespace Tango.BL.Entities #endregion + #region Private Methods + + private double GetLength() + { + return Segments.Sum(x => x.Length) + (EnableInterSegment ? (InterSegmentLength * (Segments.Count > 0 ? Segments.Count - 1 : Segments.Count)) : 0); + } + + #endregion + #region Public Methods public BitmapSource CreateSegmentsPie(double width, double height) diff --git a/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Segment.cs b/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Segment.cs index 82596129e..f94a9de41 100644 --- a/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Segment.cs +++ b/Software/Visual_Studio/Tango.BL/EntitiesExtensions/Segment.cs @@ -14,6 +14,9 @@ namespace Tango.BL.Entities { public partial class Segment { + private double _lastLength; + private LinearGradientBrush _brush; + public override void Save(ObservablesContext context) { for (int i = 0; i < BrushStops.Count; i++) @@ -28,9 +31,10 @@ namespace Tango.BL.Entities { base.RaisePropertyChanged(propName); - if (propName == nameof(Length)) + if (propName == nameof(Length) && _lastLength != Length) { BrushStops.ToList().ForEach(x => x.RaiseOffsetChanged()); + _lastLength = Length; } if (propName == nameof(BrushStops)) @@ -102,20 +106,7 @@ namespace Tango.BL.Entities { get { - GradientStopCollection stops = new GradientStopCollection(); - - foreach (var stop in BrushStops.OrderBy(x => x.StopIndex)) - { - stops.Add(new GradientStop(stop.Color, stop.OffsetPercent / 100d)); - } - - LinearGradientBrush brush = new LinearGradientBrush(); - brush.StartPoint = new Point(0, 0); - brush.EndPoint = new Point(1, 0); - - brush.GradientStops = stops; - - return brush; + return GetSegmentBrush(); } } @@ -160,20 +151,34 @@ namespace Tango.BL.Entities public LinearGradientBrush GetSegmentBrush() { - GradientStopCollection stops = new GradientStopCollection(); - - foreach (var stop in BrushStops.OrderBy(x => x.StopIndex)) + if (_brush == null || _brush.GradientStops.Count != BrushStops.Count) { - stops.Add(new GradientStop(stop.Color, stop.OffsetPercent / 100d)); - } + GradientStopCollection stops = new GradientStopCollection(); - LinearGradientBrush brush = new LinearGradientBrush(); - brush.StartPoint = new Point(0, 0); - brush.EndPoint = new Point(1, 0); + foreach (var stop in BrushStops.OrderBy(x => x.StopIndex)) + { + stops.Add(new GradientStop(stop.Color, stop.OffsetPercent / 100d)); + } - brush.GradientStops = stops; + LinearGradientBrush brush = new LinearGradientBrush(); + brush.StartPoint = new Point(0, 0); + brush.EndPoint = new Point(1, 0); + + brush.GradientStops = stops; - return brush; + _brush = brush; + return brush; + } + else + { + for (int i = 0; i < BrushStops.Count; i++) + { + _brush.GradientStops[i].Color = BrushStops[i].Color; + _brush.GradientStops[i].Offset = BrushStops[i].OffsetPercent / 100d; + } + + return _brush; + } } public System.Drawing.Brush CreateGdiBrush(int width, int height) diff --git a/Software/Visual_Studio/Tango.Touch/Controls/TouchNumericTextBox.cs b/Software/Visual_Studio/Tango.Touch/Controls/TouchNumericTextBox.cs index 09b5e8f96..50c478acc 100644 --- a/Software/Visual_Studio/Tango.Touch/Controls/TouchNumericTextBox.cs +++ b/Software/Visual_Studio/Tango.Touch/Controls/TouchNumericTextBox.cs @@ -21,6 +21,7 @@ namespace Tango.Touch.Controls private TextBox _text_box; private bool _prevent_text_change; private TextBlock _text_block; + private double _lastValue; Regex regex_integer = new Regex(@"^[0-9]*(?:[0-9]*)?$"); Regex regex_double = new Regex(@"^[0-9]*(?:\.[0-9]*)?$"); @@ -179,10 +180,16 @@ namespace Tango.Touch.Controls } } - BindingExpression b = GetBindingExpression(ValueProperty); - if (b != null) + if (Value != _lastValue) { - b.UpdateSource(); + BindingExpression b = GetBindingExpression(ValueProperty); + + if (b != null) + { + b.UpdateSource(); + } + + _lastValue = Value; } } -- cgit v1.3.1