0

I'm attempting to Display an UIView on an external monitor in iOS if one is detected. I am able to detected and display a simple UIView using the following code...

        public void CheckForExternalDisplay()
    {
        if (UIScreen.Screens.Length > 1)
        {
            Mvx.Trace(MvxTraceLevel.Diagnostic, "Multiple screens found");
            var externalScreen = UIScreen.Screens[1];
            var rect = new RectangleF(new PointF(0, 0), externalScreen.AvailableModes.Max(m => m).Size);
            var window = new UIWindow(rect)
                {
                    Screen = UIScreen.Screens[1],
                    ClipsToBounds = true,
                    Hidden = false
                };

            var presenterView = new PresenterView(rect);
            window.AddSubview(presenterView);
        }

    }

This UIView is Very Simple. It contains a UILabel and a RadialProgress View. Most of the heavy lifting to determine what the values should be are already being done on another viewmodel that is updating a view attached to a screen on the phone. I have tried several techniques to try and get the UIView on the external display to update.

  1. Using MvxMessenger. - I tried passing a message to both a new ViewModel and to the View itself. The new ViewModel received the message only after I created a new instance from the publishing viewmodel. However, I could never intercept messages directly from the view...
  2. Delay binding and regular fluent binding where the bound viewmodel properties are simply updated from another viewmodel.
  3. Attempted to bind this View with a viewmodel already associated with another view.
  4. Wishing in one hand, and crapping in the other... Guess which one filled up first ;)

It's almost as if the UIview (below), isn't being registered/associated with a viewmodel. I'm sure I'm missing something somewhere. As always, I appreciate the help!

   public sealed class PresenterView
    : MvxView
{
    private readonly RadialProgressView _progressView;
    private readonly MvxSubscriptionToken _token;
    private IMvxMessenger _messenger;
    private UILabel _displayLabel;

    public PresenterView(RectangleF frame)
        : base(frame)
    {
        Frame = frame;

        _messenger = Mvx.Resolve<IMvxMessenger>();
        _token = _messenger.Subscribe<DisplayMessage>(OnDisplayMessageReceived);

        _displayLabel = new UILabel
            {
                AdjustsFontSizeToFitWidth = true,
                Lines = 1,
                LineBreakMode = UILineBreakMode.TailTruncation,
                Text = "This is a workout",
                Font = UIFont.FromName("rayando", 96f),
                BackgroundColor = UIColor.Clear,
                PreferredMaxLayoutWidth = Frame.Width - 10,
                Frame = new RectangleF(0, 0, Frame.Width - 10, frame.Height / 7),
                TextColor = UIColor.White,
                TextAlignment = UITextAlignment.Center,
                AutoresizingMask = UIViewAutoresizing.All
            };

        AddSubview(_displayLabel);

        _progressView = new RadialProgressView
            {
                Center = new PointF(Center.X, Center.Y),
                MinValue = 0f,
            };

        AddSubview(_progressView);

        this.DelayBind(() =>
          {
        MvxFluentBindingDescriptionSet<PresenterView, PresenterViewModel> set =
            this.CreateBindingSet<PresenterView, PresenterViewModel>();
        set.Bind(_progressView).For(pv => pv.Value).To(vm => vm.ClockValue);
        set.Bind(_progressView).For(pv => pv.MaxValue).To(vm => vm.MaxProgress);
        set.Bind(_workoutLabel).To(vm => vm.DisplayText);
        set.Apply();
          }); 
    }

    private void OnDisplayMessageReceived(DisplayMessage obj)
    {
        _workoutLabel.Text = obj.Message;
    }
}

I do realize that I have included both solutions here. I did try each of them independently.

blakeD
  • 97
  • 1
  • 4

1 Answers1

0

From the code you've posted, I can't see anywhere you are actually setting the data context for your view.

In 'normal mvvmcross' either:

  • an MvxViewController creates its own DataContext (ViewModel) using its show request in viewDidLoad
  • some other app code sets an MvxView's DataContext based on app- specific logic - see n=32 in http://mvvmcross.wordpress.com as an example

In your code, i can't currently see where you set this - so try setting view.DataContext somewhere.

Stuart
  • 66,722
  • 7
  • 114
  • 165
  • Thanks for the help! I tried setting the Data context as suggested, but still no luck. Basically what I did was to create an instance of the view that is displayed on the external screen in the ViewDidLoad event of another view that has the external ViewModel as a property. I then bound the external view DataContext to that property, but none of the data seems to update. Is this because the view I'm trying to update is actually on a different Window/UIScreen altogether? – blakeD Jul 04 '13 at 04:47
  • "I tried... I then bound... Is this because ... ?". Sorry - this is too hard to follow. Try looking at the debug trace, try including more code in your question try putting in breakpoints and seeing what variables are, try posting a full repo. Sorry - I find details in comments really hard to read - they just feel so much harder to read and understand than full questions/answers here. – Stuart Jul 04 '13 at 08:31
  • Stuart - Once again I appreciate the feedback! I apologize for the confusion I created by placing too many details in the comments. I created a simple project that reflects what I'm trying to accomplish, but still receive the same results. I have push the project to GitHub. I can be found at the following [link](https://github.com/davidsonblake/SimpleExternalScreen) – blakeD Jul 04 '13 at 13:53