Search code examples
c#wpfmvvmrefreshadorner

How to refresh / update the wpf window after adorner has been added / enabled


I am having some troubles with the Adorner of WPF. My adorner is ok, but I don't get it displayed at the very moment I want to.

I like to do something like:

    public void MyAction()
    {
        // property bound to the adorner VisibiltyProperty
        // I like the happen a refresh now
        // (code is wired correct, if I finish method here, the adorner is drawn)
        this.IsAdornerEnabled = true;

        try
        {
           ... doing some long lasting things I cannot do async cause it depends on a lot of objects owned by main thread...
        }
        finally
        {
            // I like the adorner to be removed from UI now
            this.IsAdornerEnabled = false;
        }
    }

The IsAdornerEnabled Property is correct bound to the adorner and makes a notification to it. But in this code the adorner is painted and removed for a split second when the method terminates.

How is it possible to get it rendered before the UI is thread is blocked?

Any help is very appreciated.

Explanation: I like to use the adorner to create a non-clickable, half transparent pane over my main tab with a text like "loading module" on it. While my MainThread is navigating with magellan, resolving dependencies with castle and then creating a lof of DevExpress controls, I like to show this pane. Then I remove it again. I can create the adorner, that's no problem. The adorner works in my prototyping project, where I don't do any other things.


Solution

  • I found the solution for my answer. It might no be the ultra clean way, but it works for me.

    ViewModel:

        private void LoadUi()
        {
            try
            {
                this.IsAdornerVisible = true;
                RefreshCallback();
    
                ... some long going view initialization...
            }
            finally
            {
                this.IsAdornerVisible = false;
            }
    }
    

    RefreshCallback is a property of type action, set by a method in code behind of the xaml. The method set to the RefreshCallback is this one:

        private void Refresh()
        {
            this.Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle, null);
        }
    

    The invoke on the dispatcher with ContextIdle makes that the rendering is done before the empty action is executed. With ContextIdle this works good. Before I tried other values of DispatcherPriority, for example Render. Did not work. Now I'm happy it works and weekend can begin.

    The solution I found here: Source of my solution: Update the WPF UI now: how to wait for the rendering to finish