Accessing View from ViewModel Having a view (grid control) that provides some functionallity via methods (primary SerializeView / DeserializeView) that should be called from the view model which is bound to the view.

One point to consinder is, that the view model may not be bound to the view during the deserialization process. Therefore, the serialization state of the view must be buffered in the view model and applied when the view model will be bound to the view.

The following solution can handle such use cases in general:

Implementation

IViewAwareViewModel interface that must be implemented by the view model:

public interface IViewAwareViewModel&lt;TView&gt; where TView : class
{
    ViewConnection&lt;TView&gt; ViewConnection { get; }
}


ViewConection that encapsulates the view and provides "delayed access".

public class ViewConnection&lt;TView&gt; where TView : class
{
    private TaskCompletionSource&lt;TView&gt; taskCompletionSource = new TaskCompletionSource&lt;TView&gt;();

    public Task&lt;TView&gt; View =&gt; this.taskCompletionSource.Task;

    public bool IsConnected =&gt; this.taskCompletionSource.Task.IsCompleted;

    public void Release()
    {
        this.taskCompletionSource = new TaskCompletionSource&lt;TView&gt;();
    }

    public void RunOnView(Action&lt;TView&gt; action)
    {
        this.View.ContinueWith(task =&gt; action(task.Result));
    }

    internal void SetView(TView view)
    {
        if (this.IsConnected)
        {
            throw new InvalidOperationException("Unable to connect to a view twice.");
        }
        this.taskCompletionSource.SetResult(view);
    }
}


ViewConnector that provides a helper method for connecting the view with the view model.

public static class ViewConnector&lt;TView&gt; where TView : class
{
    public static void Register(FrameworkElement target)
    {
        if (target == null)
        {
            throw new ArgumentNullException(nameof(target));
        }

        if (!typeof(TView).IsInstanceOfType(target))
        {
            throw new InvalidOperationException($"Object of type '{target.GetType()}' is not compatible to type '{typeof(TView)}'.");
        }

        target.DataContextChanged += TargetDataContextChanged;
    }

    private static void TargetDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        var oldViewModel = e.OldValue as IViewAwareViewModel&lt;TView&gt;;
        var newViewModel = e.NewValue as IViewAwareViewModel&lt;TView&gt;;

        if (oldViewModel != null)
        {
            oldViewModel.ViewConnection?.Release();
        }

        if (newViewModel != null)
        {
            newViewModel.ViewConnection.SetView(sender as TView);
        }
    }
}


Usage

View Registration

var dataGrid = new MyDataGrid(); // implements: IDataGridAbstractionForViewModel
ViewConnector&lt;IDataGridAbstractionForViewModel&gt;.Register(dataGrid);


ViewModel Implementaion

public class DataGridViewModel : ViewModelBase, IViewAwareViewModel&lt;IDataGridAbstractionForViewModel&gt;
{
    public ViewConnection&lt;IDataGridAbstractionForViewModel&gt; ViewConnection { get; } = new ViewConnection&lt;IDataGridAbstractionForViewModel&gt;();

    protected override string SerializeState()
    {
        if (this.ViewConnector.IsConnected)
        {
            var view = this.ViewConnection.View.Result;
            return view.SaveLayout();
        }

        return string.Empty;
    }

    protected override void DeserializeState(string state)
    {
        base.DeserializeState(state);

        if (string.IsNullOrEmpty(state))
        {
            return;
        }

        this.ViewConnection.RunOnView(view =&gt; view.RestoreLayout(state));

    }

    protected override void OnRemoved()
    {
        base.OnRemoved();

        this.ViewConnection.Release();
    }
}


Questions


Are there other cleaner solutions / approaches?
Do you see any risk of memory leaks?
General feedback? :)
ViewConnection class looks cool, I think that's a clever use of tasks. But frankly I don't see why you can't have a 

public string State { get {...} set {...}}


property on both view and viewmodel and solve your problem with two-way databinding. You can set this property on your viewmodel when you load your layout. If view is there - fine, it will be notified that the property has changed and you can handle this change on the view side (i.e. update datagrid with new state). If the view is not there - also fine, it will fetch the property from viewmodel as soon as you set its DataContext. In similar fashion you can save datagrid state on view side, set View.State and handle the new state in ViewModel.State property (i.e save it to file). You do not show your view class, but I don't see any problems with this approach off the bat, and I think that's how those things should be done normally.