From ed582a9fde3aef0a2cd9462cbe66c9dc1446076d Mon Sep 17 00:00:00 2001 From: aldelaro5 Date: Wed, 3 Aug 2022 22:39:40 -0400 Subject: [PATCH 1/2] Implement DataContext update notifications on the DataGrid This fixes #5661 by allowing the DataGrid to notify its cells that their DataContext is about to be changed. --- src/Avalonia.Controls.DataGrid/DataGrid.cs | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/Avalonia.Controls.DataGrid/DataGrid.cs b/src/Avalonia.Controls.DataGrid/DataGrid.cs index d42468f47e..f4cd425c53 100644 --- a/src/Avalonia.Controls.DataGrid/DataGrid.cs +++ b/src/Avalonia.Controls.DataGrid/DataGrid.cs @@ -2167,6 +2167,38 @@ namespace Avalonia.Controls return desiredSize; } + + /// + protected override void OnDataContextBeginUpdate() + { + base.OnDataContextBeginUpdate(); + foreach (DataGridRow row in GetAllRows()) + { + foreach (DataGridCell cell in row.Cells) + { + if (cell.Content is StyledElement) + { + DataContextProperty.Notifying?.Invoke((IAvaloniaObject)cell.Content, true); + } + } + } + } + + /// + protected override void OnDataContextEndUpdate() + { + base.OnDataContextEndUpdate(); + foreach (DataGridRow row in GetAllRows()) + { + foreach (DataGridCell cell in row.Cells) + { + if (cell.Content is StyledElement) + { + DataContextProperty.Notifying?.Invoke((IAvaloniaObject)cell.Content, false); + } + } + } + } /// /// Raises the BeginningEdit event. From ee662cecdd0c9b57f986d44e93afa26b5d524b3e Mon Sep 17 00:00:00 2001 From: ili Date: Mon, 8 Aug 2022 20:13:47 +0500 Subject: [PATCH 2/2] Avoid lock in timers --- .../AndroidThreadingInterface.cs | 45 +++++++---------- .../InternalPlatformThreadingInterface.cs | 4 +- .../HeadlessPlatformThreadingInterface.cs | 48 +++++++++---------- 3 files changed, 42 insertions(+), 55 deletions(-) diff --git a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs index 42f75a27e1..de9149e9a1 100644 --- a/src/Android/Avalonia.Android/AndroidThreadingInterface.cs +++ b/src/Android/Avalonia.Android/AndroidThreadingInterface.cs @@ -27,46 +27,33 @@ namespace Avalonia.Android { if (interval.TotalMilliseconds < 10) interval = TimeSpan.FromMilliseconds(10); - object l = new object(); + var stopped = false; Timer timer = null; - var scheduled = false; timer = new Timer(_ => { - lock (l) + if (stopped) + return; + + EnsureInvokeOnMainThread(() => { - if (stopped) + try { - timer.Dispose(); - return; + tick(); } - if (scheduled) - return; - scheduled = true; - EnsureInvokeOnMainThread(() => + finally { - try - { - tick(); - } - finally - { - lock (l) - { - scheduled = false; - } - } - }); - } - }, null, TimeSpan.Zero, interval); + if (!stopped) + timer.Change(interval, Timeout.InfiniteTimeSpan); + } + }); + }, + null, interval, Timeout.InfiniteTimeSpan); return Disposable.Create(() => { - lock (l) - { - stopped = true; - timer.Dispose(); - } + stopped = true; + timer.Dispose(); }); } diff --git a/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs b/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs index 630d2d8efb..e1f6db9c60 100644 --- a/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs +++ b/src/Avalonia.Controls/Platform/InternalPlatformThreadingInterface.cs @@ -43,7 +43,7 @@ namespace Avalonia.Controls.Platform _priority = priority; _interval = interval; _tick = tick; - _timer = new Timer(OnTimer, null, interval, TimeSpan.FromMilliseconds(-1)); + _timer = new Timer(OnTimer, null, interval, Timeout.InfiniteTimeSpan); _handle = GCHandle.Alloc(_timer); } @@ -57,7 +57,7 @@ namespace Avalonia.Controls.Platform if (_timer == null) return; _tick(); - _timer?.Change(_interval, TimeSpan.FromMilliseconds(-1)); + _timer?.Change(_interval, Timeout.InfiniteTimeSpan); }); } diff --git a/src/Avalonia.Headless/HeadlessPlatformThreadingInterface.cs b/src/Avalonia.Headless/HeadlessPlatformThreadingInterface.cs index e42a7b1a71..b233b46dd0 100644 --- a/src/Avalonia.Headless/HeadlessPlatformThreadingInterface.cs +++ b/src/Avalonia.Headless/HeadlessPlatformThreadingInterface.cs @@ -36,35 +36,35 @@ namespace Avalonia.Headless public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick) { - var cancelled = false; - var enqueued = false; - var l = new object(); - var timer = new Timer(_ => + if (interval.TotalMilliseconds < 10) + interval = TimeSpan.FromMilliseconds(10); + + var stopped = false; + Timer timer = null; + timer = new Timer(_ => { - lock (l) + if (stopped) + return; + + Dispatcher.UIThread.Post(() => { - if (cancelled || enqueued) - return; - enqueued = true; - Dispatcher.UIThread.Post(() => + try { - lock (l) - { - enqueued = false; - if (cancelled) - return; - tick(); - } - }, priority); - } - }, null, interval, interval); + tick(); + } + finally + { + if (!stopped) + timer.Change(interval, Timeout.InfiniteTimeSpan); + } + }); + }, + null, interval, Timeout.InfiniteTimeSpan); + return Disposable.Create(() => { - lock (l) - { - timer.Dispose(); - cancelled = true; - } + stopped = true; + timer.Dispose(); }); }