Окно WPF не реализует ISynchronizeInvoke.InvokeRequired ОШИБКА

У меня проблема с тем, что мое приложение WPF в его MainWindow:

public partial class MainWindow : Window, ICallbackNotify

этот " ICallbackNotify " предназначен для связи с MapInfo COM и обеспечения интерактивности между UI и MapInfo.

public interface ICallbackNotify : ISynchronizeInvoke
{
    // Method called by MapInfoCallback class when user chooses custom OLE menuitem 
    void OnMenuItemClick(uint id);

    // Method called by MapInfoCallback class when the status bar text changes 
    void OnStatusBarTextChanged(string text);

    // Method called by MapInfoCallback class when window changes
    void OnWindowContentsChanged(uint windowId);
}

Проблема в том, что этот код отлично работает в Windows From, но когда я помещаю его в WPF, появляется сообщение ERROR:

Error   1   'WpfApplication3.MainWindow' does not implement interface member 'System.ComponentModel.ISynchronizeInvoke.InvokeRequired'  c:\users\dragon\documents\visual studio 2010\Projects\WpfApplication3\WpfApplication3\MainWindow.xaml.cs    25  26  WpfApplication3

и я не могу понять, почему и как решить эту проблему


person moaaz    schedule 20.07.2011    source источник
comment
Вам нужно использовать Dispatcher.CheckAccess().   -  person Hans Passant    schedule 20.07.2011
comment
как и где? видите, проблема в том, что я хочу, чтобы главное окно наследовалось от IcallbackNotify, но я не могу, потому что появляется эта ошибка, а главное окно не может наследоваться от ICallbackNotify, поэтому я действительно не знаю, что делать   -  person moaaz    schedule 21.07.2011


Ответы (1)


Под капотом Windows Forms и WPF очень разные.

ISynchronizeInvoke — это концепция Windows Form, основанная на Win32 API, которая не применяется к WPF. В WPF мы используем Dispatcher для связи между потоками.

Судя по вашему вопросу, вы хотите разместить элемент управления WinForms COM внутри приложения WPF. Чтобы соединить эти две технологии, у Microsoft есть элемент управления WindowsFormHost, который можно использовать для хранения вашего компонента. В этом сообщении в блоге содержится довольно хорошее описание это. Ознакомьтесь с этим примером MSDN: https://msdn.microsoft.com/en-us/library/vstudio/ms751761(v=vs.100).aspx


Обновление:

Похоже, проблема у вас не во время выполнения, а во время компиляции ?? Позвольте замедлиться и быть ясным:

В Windows Forms все пользовательские элементы управления и окна реализуют ISynchronizeInvoke. WPF не построен на традиционном конвейере сообщений Win32 WinProc, поэтому он не реализует этот интерфейс. Если вы скопируете и вставите свой интерфейс и реализацию INotifyCallBack "как есть" в файл MainWindow.xaml.cs, вы получите ошибку компиляции, потому что базовый интерфейс ISynchronizeInvoke не реализован в этом классе. Чтобы обойти ошибку компиляции, вам придется реализовать сигнатуру ISynchronizeInvoke:

public partial class MainWindow : Window, ISynchronizeInvoke
{
   public IAsyncResult BeginInvoke(Delegate method, object[] args)
   {
      throw new NotImplementedException();
   }
   public object EndInvoke(IAsyncResult result)
   {
      throw new NotImplementedException();
   }
   public object Invoke(Delegate method, object[] args)
   {
      throw new NotImplementedException();
   }
   public bool InvokeRequired
   {
      throw new NotImplementedException();
   }
}

Но знаете что? Если вы сделаете это, вы должны обеспечить правильное сопоставление между ISynchronizeInvoke и диспетчером WPF. Поэтому не делайте этого! Приведенный выше код может скомпилироваться, но, скорее всего, будет работать некорректно (или вообще не будет работать).

Вместо этого используйте возможности интеграции Windows Form, предоставляемые корпорацией Майкрософт, для размещения элемента управления внутри элемента управления WindowsFormHost. Поскольку вам необходимо внедрить пользовательский код в свой INotifyCallback, вам потребуется поместить этот код в пользовательский элемент управления Windows Forms.

В общем, вам нужно следовать указаниям, указанным в статье, указанной выше:

  • Ссылка на System.Windows.Forms.dll и WindowsFormsIntegration.dll
  • Добавьте соответствующие пространства имен в ваш MainWindow.xaml.
  • Добавьте WindowsFormsHost в качестве контейнера в файл MainWindow.xaml, а затем поместите в него свой собственный элемент управления.

Поэтому вместо того, чтобы размещать реализацию ICallbackNotify в WPF MainWindow, поместите ее в стандартный пользовательский элемент управления Windows Form:

namespace YourProject {
   using System.ComponentModel;
   using System.Windows.Forms;

   public class MyCustomMapControl : UserControl, ICallbackNotify
   {
       // your custom code goes here
   }
}
person bryanbcook    schedule 20.07.2011
comment
ну, это не совсем то, что я имел в виду, этот класс ICallbackNotify реализует ISynchronizeInvoke, но когда мы подходим к главному окну, он реализует ICallbackNotify, но wpf печатает ошибку выше. как я могу унаследовать ICallbackNotify из главного окна и одновременно избежать этой ошибки? - person moaaz; 21.07.2011
comment
Я обновил сообщение, чтобы предоставить дальнейшие указания. Короче говоря, WPF не очень хорошо справляется с элементами управления COM, и вам нужно добавить некоторые дополнительные возможности. - person bryanbcook; 21.07.2011
comment
Исходная ссылка на это не работает, вместо этого предложите использовать внутреннюю ссылку переполнения стека: в поток диспетчера в wpf"> stackoverflow.com/questions/11725191/ - person Jeremy; 28.08.2015