Xamarin.Mac 尽管有 NeedsDisplay,但未调用 NSView DrawRect

Xamarin.Mac NSView DrawRect not called despite NeedsDisplay

我正在尝试创建一个视图,表示在另一个视图中水平移动的垂直线。

我有以下 ViewController 和自定义视图。

using System;
using System.Timers;
using AppKit;
using CoreGraphics;

namespace CustomControlExperiment
{
    public partial class ViewController : NSViewController
    {
        private Timer _timer;
        private LineControl _lineControl;

        public ViewController(IntPtr handle) : base(handle)
        {
        }

        public override void ViewDidLoad()
        {
            base.ViewDidLoad();

            var frame = new CGRect { X = 0, Y = 0, Height = ContentView.Frame.Height, Width = 1 };
            _lineControl = new LineControl(frame);

            ContentView.AddSubview(_lineControl);

            _timer = new Timer(500);
            _timer.Elapsed += _timer_Elapsed;
            _timer.Start();

        }

        private void _timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            _lineControl.Position++;
        }
    }

    public class LineControl : NSView
    {
        private float _position;

        public LineControl(CGRect frameRect) : base(frameRect)
        {
            Initialize();
        }

        private void Initialize()
        {
            WantsLayer = true;
        }

        public override void DrawRect(CGRect dirtyRect)
        {
            Console.WriteLine("DrawRect");
            base.DrawRect(dirtyRect);

            var context = NSGraphicsContext.CurrentContext?.CGContext;

            if (context == null)
            {
                return;
            }

            var height = Frame.Height;

            context.SetStrokeColor(new CGColor(.5f, .6f, .7f));
            context.SetLineWidth(1f);
            context.SetLineDash(0, new nfloat[] { 3, 3 });

            context.MoveTo(0, 0);
            context.AddLineToPoint(0, height);

            context.StrokePath();
        }

        public float Position
        {
            get => _position;
            set
            {
                _position = value;
                Console.WriteLine("Position = " + _position);

                NeedsDisplay = true;
            }
        }
    }
}

DrawRect 在程序第一次运行时被调用一次运行。之后它不再被调用,尽管 Position 被增加并且 NeedsDisplay 被设置。

我做错了什么?

System.Timers.Timer elapsed 事件在线程池线程上 运行 - 在主线程外设置 needsDisplay 是非法的。如果您在 Xcode 中尝试此操作,这是线程清理程序的 运行 时间错误。

您需要修改您的代码,以便从主线程更新 Position,或者将设置 needsDisplay 的调用编组到主线程。

在 .NET 和 Xamarin 中有多种方法 - here 是一份建议使用 InvokeOnMainThread 的文档(它适用于 iOS,但我相信它也适用于 macOS) .