【问题标题】:Replacing the WPF entry point替换 WPF 入口点
【发布时间】:2011-09-03 15:13:33
【问题描述】:

WPF 定义了自己的Main() 方法。我应该如何用我自己的 Main 方法替换它,该方法(通常)打开 WPF MainWindow(例如,通过命令行参数添加非 WPF 脚本模式)?

【问题讨论】:

    标签: .net wpf entry-point


    【解决方案1】:

    一些示例描述了将 App.xaml 的构建操作从 ApplicationDefinition 更改为 Page 并编写自己的 Main() 来实例化 App 类并调用其 Run() 方法,但这可能会在App.xaml 中应用程序范围资源的解析。

    相反,我建议在自己的类中创建自己的Main(),并在项目属性中将启动对象设置为该类:

    public class EntryPoint {
        [STAThread]
        public static void Main(string[] args) {
            if (args != null && args.Length > 0) {
                // ...
            } else {
                var app = new App();
                app.InitializeComponent();
                app.Run();
            }
        }
    }
    

    我这样做是为了利用一些AppDomain 事件,这些事件必须在其他任何事情发生之前订阅(例如AssemblyResolve)。我遇到的将 App.xaml 设置为 Page 的不良后果包括我的 UserControl 视图 (M-V-VM) 在设计时无法解析 App.xaml 中保存的资源。

    【讨论】:

    • 好的,我正在调用 App.Main() 而不是 Run(),因为 Main() 调用 InitializeComponent(),它会安装 Startup 事件处理程序。我猜如果您将 Build Action 更改为 Page(因为 Main() 消失),您必须调用 Run() 但我只是将其保留为 ApplicationDefinition。
    • 生成的Main()只是实例化App并调用Run()Startup 事件在System.Windows.Application 的构造函数中触发。 Run() 附加 Dispatcher 并开始消息泵。 InitializeComponent() 应该在 Apps 的构造函数中调用。不是吗?
    • 我将构造函数添加到App 并在那里调用InitializeComponent() 以避免App.Main()。为简洁起见,其余部分我过于简化了。 StartupApplication.OnStartup() 触发,只有派生的App 类的构造函数可以在触发之前订阅Startup。这是因为Application 的构造函数异步调用了一个调用OnStartup() 的方法,所以它实际上是在基构造函数和派生构造函数完成后运行的。
    • 不必解析定义的“主要”入口点内的命令行参数,是否有某种方法可以将这些参数传递给方法中定义的 WPF 应用程序实例,以便它们可以由定义的“启动”(或 OnStartup)覆盖(通过 e.Args 属性)处理?
    • 不用移动(或复制)App.Main(),您只需添加它并将其设置为项目的入口点,然后直接调用App.Main()
    【解决方案2】:

    通常我会编辑 App.xaml 以添加此支持:

    <Application x:Class="SomeNamespace.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             Startup="Application_Startup">
    

    相关部分是我从StartupUri 更改为Startup,并在App.xaml.cs 中使用了一个事件处理程序。这是一个例子:

    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            int verbose = 0;
            var optionSet = new OptionSet
            {
                { "v|verbose", "verbose output, repeat for more verbosity.",   
                        arg => verbose++ }
            };
    
            var extra = optionSet.Parse(e.Args);
            var mainWindow = new MainWindow(verbose);
            mainWindow.Show();
        }
    }
    

    【讨论】:

    • 尽管使用这种方法,除非您从命令窗口运行它,否则您将看不到任何Console.* 输出。
    • 这种方法让我可以将构造函数参数传递给主窗口,这很好。我什至可以将它与 Joel 的方法结合起来。
    • 感谢您指出它是“Startup”而不是“StartupUri”!
    【解决方案3】:

    伙计们 问题是你的程序有两个静态 Main() 方法,这会导致编译器抱怨;要解决此问题,请尝试以下方法之一:

    • 告诉编译器您的静态 Main() 方法应该是执行入口点 — 将项目的“启动对象”设置设置为包含您的静态 Main() 方法的类(在解决方案资源管理器中右键单击项目,选择“属性”,然后在“应用程序”选项卡下查找“启动对象”设置)。
    • 关闭自动生成 App.g.cs 的静态 Main() 方法——在解决方案资源管理器中,右键单击 App.xaml,选择“属性”,然后将“构建操作”从“应用程序定义”更改为“页面” ”。

    【讨论】:

    • 谢谢;第二个要点至关重要 - 巧妙地放在那里!
    【解决方案4】:

    使用您的自定义静态 Main 方法创建新类。在这个方法的最后,只需调用 WPF 生成的原始 App.Main():

    public class Program
    {
        [STAThread]
        public static void Main(string[] args)
        {
            // Your initialization code
            App.Main();
        }
    }
    

    然后将项目的“启动对象”设置为包含静态 Main() 的类。

    【讨论】:

      【解决方案5】:

      使用自定义 Main() 可能会遇到问题,因为未设置 StartupUri。

      您可以使用它在您的 App 类中轻松设置它(不要忘记从 App.xaml 中删除 StartupUri 并将其 Build Action 设置为 Page):

      [STAThread]
      static void Main()
      {
          App app = new App();
          app.InitializeComponent();
          app.Run();
      }
      
      protected void OnStartup(object sender, StartupEventArgs e)
      {
              var toUri = new UriTypeConverter();
              StartupUri = (Uri)toUri.ConvertFrom("MainWindow.xaml");
      ...
      }
      

      【讨论】:

        猜你喜欢
        • 2020-03-09
        • 1970-01-01
        • 2017-06-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-11
        相关资源
        最近更新 更多