Окно WPF не реализует ISynchronizeInvoke.InvokeRequired ОШИБКА - PullRequest
0 голосов
/ 20 июля 2011

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

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 , появляется ОШИБКА msg:

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

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

1 Ответ

2 голосов
/ 20 июля 2011

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

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

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


Обновление:

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

В Windows Forms все пользовательские элементы управления и окна реализуют ISynchronizeInvoke. WPF не построен на традиционном Win32c-обработчике сообщений Win32, поэтому они не реализуют этот интерфейс. Если вы скопируете и вставите свой интерфейс 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, предоставленные Microsoft, для размещения вашего элемента управления внутри элемента управления WindowsFormHost. Поскольку вам необходимо внедрить пользовательский код в свой INotifyCallback, вам нужно поместить этот код в пользовательский элемент управления пользовательских окон .

.

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

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

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

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

   public class MyCustomMapControl : UserControl, ICallbackNotify
   {
       // your custom code goes here
   }
}
...