如何从另一个页面调用 MainWindow 上的方法

How to call a method on MainWindows from another Page

我在同一个命名空间中有 MainWindow.xaml 和另一个 Page.xaml

MainWindow 上有文本块和框架。

MainWindow 上的框架显示 Page.xaml,该页面上有一个按钮。

我想用那个按钮在 MainWindow 中调用非静态方法,但我不知道如何:(

例如:

MainWindow.xaml.cs

    namespace wpfapp
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            openframe();
        }

        private void openframe()
        {
            frame1.Source = new Uri("testapge.xaml", UriKind.Relative);

        }
        public void MyMethod()
        {
            textblock1.Text = "This text is showed on MainWindow if i click to the Button";
        }    
    }
}

Page.xaml.cs

    namespace wpfapp
{
    public partial class Page : Page
    {
        public Page()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            MainWindow trytocallit = new MainWindow();
            trytocallit.MyMethod();
        }
    }
}

这当然不行。感谢您的帮助!

好吧,这样做听起来不对,但是如果您必须在内存中获取对象而不是创建一个新对象..

但是这个剂量听起来不错..告诉我们你为什么要这样做,以便我们可以提出更好的方法

--- 只是为了让您的案例奏效.. 这样做..

主要window --

public static MainWindow Instance { get; private set; }

    static MainWindow()
{
    Instance = new MainWindow();
}

private MainWindow()
{
    InitializeComponent();
}

在 app.xaml 中删除 StartupUri="MainWindow.xaml"

public App()
{
    Startup += App_Startup;        
}

void App_Startup(object sender, StartupEventArgs e)
{
    TestApp.MainWindow.Instance.Show();
}

现在您可以在 Page 中访问静态实例 ... 调用方法

您可以做几件不同的事情。你可以实现类似 , which is similar to the Singleton pattern.

的东西

另一种选择是使用 dependency injection 在创建 Page class 时提供 MainWindow 的一个实例。

public class Page : Page
{
  private MainWindow MainWindow;

  public Page(MainWindow mainWindow)
  {
    InitializeComponent();

    this.MainWindow = mainWindow;

    // Other constructor stuff
  } 

  // Other methods, event handlers, etc.
}

通常使用依赖注入,我们依赖抽象而不是具体实现(以减少耦合)。

public interface IMainWindowThatDoesSomething
{
  void DoSomething();
}

public class MainWindow : Window, IMainWindowThatDoesSomething
{
  // Constructor, methods, event handlers, etc. go here.

  public void DoSomething()
  {
    // Implementation here.
  } 
}

public class Page : Page
{    
  private IMainWindowThatDoesSomething mainWindow;

  public Page(IMainWindowThatDoesSomething mainWindow)
  {
    InitializeComponent();

    this.mainWindow = mainWindow;

    // Other constructor jazz.
  }

  private void UserDidSomethingAndMainWindowNeedsToReact()
  {
    mainWindow.DoSomething();
  }
}

考虑利用带参数的消息传递在对象之间传递数据。

您可以使用 EventAggregator or MessageBus.

我们的想法是让您的用户控件订阅他们想要响应的事件。

注意:

我用视图模型来做这个。 但是,我认为将此代码添加到用户控件时会产生代码味道,无论使用它们的应用程序如何,都应具有一般用途。

我使用 发布订阅模式 来处理复杂的 class-依赖关系:

ViewModel:

    public class ViewModel : ViewModelBase
    {
        public ViewModel()
        {
            CloseComand = new DelegateCommand((obj) =>
                {
                    MessageBus.Instance.Publish(Messages.REQUEST_DEPLOYMENT_SETTINGS_CLOSED, null);
                });
        }
}

Window:

public partial class SomeWindow : Window
{
    Subscription _subscription = new Subscription();

    public SomeWindow()
    {
        InitializeComponent();

        _subscription.Subscribe(Messages.REQUEST_DEPLOYMENT_SETTINGS_CLOSED, obj =>
            {
                this.Close();
            });
    }
}

您可以利用 Bizmonger.Patterns 获取 MessageBus。

MessageBus

public class MessageBus
{
    #region Singleton
    static MessageBus _messageBus = null;
    private MessageBus() { }

    public static MessageBus Instance
    {
        get
        {
            if (_messageBus == null)
            {
                _messageBus = new MessageBus();
            }

            return _messageBus;
        }
    }
    #endregion

    #region Members
    List<Observer> _observers = new List<Observer>();
    List<Observer> _oneTimeObservers = new List<Observer>();
    List<Observer> _waitingSubscribers = new List<Observer>();
    List<Observer> _waitingUnsubscribers = new List<Observer>();

    int _publishingCount = 0;
    #endregion

    public void Subscribe(string message, Action<object> response)
    {
        Subscribe(message, response, _observers);
    }

    public void SubscribeFirstPublication(string message, Action<object> response)
    {
        Subscribe(message, response, _oneTimeObservers);
    }

    public int Unsubscribe(string message, Action<object> response)
    {
        var observers = new List<Observer>(_observers.Where(o => o.Respond == response).ToList());
        observers.AddRange(_waitingSubscribers.Where(o => o.Respond == response));
        observers.AddRange(_oneTimeObservers.Where(o => o.Respond == response));

        if (_publishingCount == 0)
        {
            observers.ForEach(o => _observers.Remove(o));
        }

        else
        {
            _waitingUnsubscribers.AddRange(observers);
        }

        return observers.Count;
    }

    public int Unsubscribe(string subscription)
    {
        var observers = new List<Observer>(_observers.Where(o => o.Subscription == subscription).ToList());
        observers.AddRange(_waitingSubscribers.Where(o => o.Subscription == subscription));
        observers.AddRange(_oneTimeObservers.Where(o => o.Subscription == subscription));

        if (_publishingCount == 0)
        {
            observers.ForEach(o => _observers.Remove(o));
        }

        else
        {
            _waitingUnsubscribers.AddRange(observers);
        }

        return observers.Count;
    }

    public void Publish(string message, object payload)
    {
        _publishingCount++;

        Publish(_observers, message, payload);
        Publish(_oneTimeObservers, message, payload);
        Publish(_waitingSubscribers, message, payload);

        _oneTimeObservers.RemoveAll(o => o.Subscription == message);
        _waitingUnsubscribers.Clear();

        _publishingCount--;
    }

    private void Publish(List<Observer> observers, string message, object payload)
    {
        Debug.Assert(_publishingCount >= 0);

        var subscribers = observers.Where(o => o.Subscription.ToLower() == message.ToLower());

        foreach (var subscriber in subscribers)
        {
            subscriber.Respond(payload);
        }
    }

    public IEnumerable<Observer> GetObservers(string subscription)
    {
        var observers = new List<Observer>(_observers.Where(o => o.Subscription == subscription));
        return observers;
    }

    public void Clear()
    {
        _observers.Clear();
        _oneTimeObservers.Clear();
    }

    #region Helpers
    private void Subscribe(string message, Action<object> response, List<Observer> observers)
    {
        Debug.Assert(_publishingCount >= 0);

        var observer = new Observer() { Subscription = message, Respond = response };

        if (_publishingCount == 0)
        {
            observers.Add(observer);
        }
        else
        {
            _waitingSubscribers.Add(observer);
        }
    }
    #endregion
}

}

订阅

public class Subscription
{
    #region Members
    List<Observer> _observerList = new List<Observer>();
    #endregion

    public void Unsubscribe(string subscription)
    {
        var observers = _observerList.Where(o => o.Subscription == subscription);

        foreach (var observer in observers)
        {
            MessageBus.Instance.Unsubscribe(observer.Subscription, observer.Respond);
        }

        _observerList.Where(o => o.Subscription == subscription).ToList().ForEach(o => _observerList.Remove(o));
    }

    public void Subscribe(string subscription, Action<object> response)
    {
        MessageBus.Instance.Subscribe(subscription, response);
        _observerList.Add(new Observer() { Subscription = subscription, Respond = response });
    }

    public void SubscribeFirstPublication(string subscription, Action<object> response)
    {
        MessageBus.Instance.SubscribeFirstPublication(subscription, response);
    }
}

作为替代和快速的解决方案,您可以使用以下代码

用法:

   MainWindow mainWindow = GetMainWindow();

方法:

    public static MainWindow GetMainWindow() 
    {
        MainWindow mainWindow=null;

        foreach (Window window in Application.Current.Windows)
        {
            Type type = typeof(MainWindow);
            if (window != null && window.DependencyObjectType.Name == type.Name)
            {
                 mainWindow = (MainWindow)window;
                if (mainWindow != null)
                {
                    break;
                }
            }
        }


        return mainWindow;

    }

抱歉回复晚了,我有一个简单的解决方案。

  • 在 Page.xaml 中创建 public 字符串变量。
  • 如果您点击页面上的按钮,变量将获得一些值。
  • 在 MainWindow 上创建新的背景 theard 并运行一个无限循环 while (true) {..}
  • 值public字符串变量一次又一次的循环控制... with Thread.Sleep(10);
  • 如果它找到一个在 MainWindow 中执行某些操作的值

它对我来说也很简单:)