MoonKnight
MoonKnight

Reputation: 23831

Binding Failure at Runtime Using MVVM

I have an EditorViewModel which contains an AvalonEditor control. I bind to the SelectionLength and SelectionStart properties of Document and everyone is happy; I can select text with both the mouse which updates the code-behind values and visa versa. Here is the issue, I am calling a C++ DLL which marshals errors back to the calling C# code via a callback, this too works well. The code to do this is

// Note, I need the call back to run on the main UI thread.
TaskScheduler scheduler = TaskScheduler.FromCurrentSynchronizationContext();
Callbacks.CompilerErrorCallback = 
    (message, documentPath, lineNumber) =>
{
    string path = String.Empty;
    Task.Factory.StartNew(async () =>
    {
        // Open the erronious file and scroll to line.
        path = Path.Combine(
            WorkingDirectory, String.Format("GDLCode\\{0}", documentPath));
        Open(path);
        //EditorViewModel evm = GetOpenEditorViewModels()
        //  .FirstOrDefault(vm => vm.FullFilePath.CompareNoCase(path));
        //if (evm != null)
        //{
        //  ActivateItem(evm);
        //  evm.SelectLine(lineNumber + 1);
        //}

        // Display error.
        await dialogManager.ShowDialog<MessageDialogResult>(
            new MessageBoxViewModel("GDECore Logic Compilation Error",
                message,
                settings));
        return;
    }, CancellationToken.None,
       TaskCreationOptions.None,
       scheduler);
};

// Run the C++ code below and pass in the `Callbacks.CompilerErrorCallback` object. 

In EditorViewModel I have

public void SelectLine(int lineNumber)
{
    DocumentLine line = Document.GetLineByNumber(lineNumber);
    SelectionStart = line.Offset;
    SelectionLength = line.Length;
}

The compiler (the C++ code) hits a compilation error and uses the callback. This is supposed to open the offending code file and highlight the offending line. The callback works and the parameters are right however, the code which is commented (which is supposed to select the offending line) out does not work. It goes into SelectLine and upon setting SelectionLength throws and ArgumentOutOfRangeException from AvalonEdit; it looks like the EditorViewModel is not bound to the underlying AvalonEditor control.

However, when I comment the offending code out and add a button to do the selection 'manually' after the code file has been opened

public void Test()
{
    EditorViewModel evm = GetOpenEditorViewModels().FirstOrDefault();
    if (evm != null)
    {
        ActivateItem(evm);
        evm.SelectLine(1);
    }
}

The selection works fine. Why is it that the AvalonEditor control does not seem to be binding to my properties immediately in the callback, is there anything I am doing that is obviously wrong?

Upvotes: 0

Views: 74

Answers (1)

AwkwardCoder
AwkwardCoder

Reputation: 25641

Can you confirm it is being called back on the UI thread?

What does the threads window in VS debugger tell you if you have a bresak point in the Task?

I would consider using the Dispatcher.Invoke method instead of Task:

Application.Current.Dispatcher.Invoke(() =>
{
   // to do something
});

Personally I would look at using Reactive Extensions (Rx .Net) to do all this, it has the ability to manage schedulers much better than Task IMO.

Upvotes: 1

Related Questions