【问题标题】:How to call a method on MainWindows from another Page如何从另一个页面调用 MainWindow 上的方法
【发布时间】:2015-05-21 03:31:36
【问题描述】:

我在同一个命名空间中有 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();
        }
    }
}

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

【问题讨论】:

    标签: c# wpf xaml methods non-static


    【解决方案1】:

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

    用法:

       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;
    
        }
    

    【讨论】:

    • 谢谢,我正在尝试,但我有一个问题:名称'ParentFinder'在当前上下文中不存在..我尝试更改它,例如 MainWindow,现在程序可以启动,但是 button1 不工作,抱歉,您可以尝试显示完整的功能代码吗?我想了解
    • 对不起,伙计,你应该把上面的方法放到任何类中调用它。对我来说,它是 ParentFinder.cs。所以我又编辑了,请看一下。
    • 好的,但是现在呢?我尝试做一些改变,它不起作用:(
    • 现在它没有错误,它很棒,但我怎样才能用它改变 texblock 值?我正在尝试,但我不知道
    • 请修改方法“public void MyMethod()”。它可以采用像 public void MyMethod(string text) 这样的字符串参数。通常你应该绑定 Textblock 的 Text 属性并通过属性更新。
    【解决方案2】:

    您可以做一些不同的事情。你可以实现类似Muds' answer的东西,它类似于Singleton pattern

    另一种选择是使用dependency injection 在创建Page 类时为其提供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();
      }
    }
    

    【讨论】:

      【解决方案3】:

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

      您可以使用EventAggregatorMessageBus

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

      注意:

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

      我使用 发布订阅模式 处理复杂的类依赖:

      视图模型:

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

      窗口:

      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。

      消息总线

      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);
          }
      }
      

      【讨论】:

        【解决方案4】:

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

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

        --- 只是为了让您的案例工作.. 这样做..

        在主窗口中--

        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 中访问静态 Instance ... 调用方法

        【讨论】:

        • 我知道,这是大错特错,它不能工作。我正在开发小程序,我在 MainWindow 上有可以更改网格背景的方法,但我必须从另一个页面调用该方法,我不知道如何:(
        • 页面和主窗口的关系是什么?
        • 我的程序在左侧有菜单,此菜单上的每个项目在右侧的框架中显示另一个页面,每个页面显示不同的内容
        • 如果我调用静态方法,那么它可以工作,但是使用静态方法我无法定义 xaml 工具(我的意思是 textbloc、标签等)及其值:(
        • 这就是我们的设计原则 :)
        【解决方案5】:

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

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

        它也适用于我:)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-11-09
          • 1970-01-01
          • 2015-05-14
          • 1970-01-01
          • 2015-06-16
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多