当前位置:首页 > 技术知识 > 正文内容

从入门到精通:揭秘WPF中App.xaml不为人知的8大黑科技

maynowei6个月前 (09-18)技术知识55

App.xaml 是 WPF 应用程序的入口点和核心配置文件,下面8个比较常用。

1、应用程序级别资源定义

如果有些资源在所有的页面都用到,我们可以把资源放到app.xaml

<Application.Resources>
    <ResourceDictionary>
        <!-- 全局样式 -->
        <Style TargetType="Button">
            <Setter Property="FontSize" Value="14"/>
            <Setter Property="Margin" Value="5"/>
        </Style>
        
        <!-- 全局数据模板 -->
        <DataTemplate DataType="{x:Type local:Customer}">
            <StackPanel>
                <TextBlock Text="{Binding Name}"/>
                <TextBlock Text="{Binding Email}"/>
            </StackPanel>
        </DataTemplate>
        
        <!-- 全局颜色和画笔 -->
        <SolidColorBrush x:Key="PrimaryColor" Color="#FF2D7D9A"/>
    </ResourceDictionary>
</Application.Resources>

2、应用程序生命周期管理

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);
        
        // 初始化操作
        InitializeServices();
        
        // 处理命令行参数
        if (e.Args.Contains("-debug"))
        {
            DebugMode = true;
        }
        
        // 创建并显示主窗口
        var mainWindow = new MainWindow();
        mainWindow.Show();
    }
    
    protected override void OnExit(ExitEventArgs e)
    {
        // 清理资源
        CleanupResources();
        base.OnExit(e);
    }
    
    public static bool DebugMode { get; private set; }
}

3、全局异常处理

写代码过程,有时会忘里加try catch,可以在这里捕捉全局异常。

public partial class App : Application
{
    public App()
    {
        // UI线程未处理异常
        this.DispatcherUnhandledException += App_DispatcherUnhandledException;
        
        // 非UI线程未处理异常
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    }
    
    private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
    {
        // 记录异常
        LogException(e.Exception);
        
        // 显示友好错误信息
        MessageBox.Show("发生未处理的异常,请联系管理员。", "错误", 
                        MessageBoxButton.OK, MessageBoxImage.Error);
        
        // 标记为已处理,防止应用程序崩溃
        e.Handled = true;
    }
    
    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        var exception = e.ExceptionObject as Exception;
        LogException(exception);
        
        // 通常无法恢复,只能记录并退出
        if (e.IsTerminating)
        {
            MessageBox.Show("应用程序即将关闭,原因是未处理的异常。", "致命错误",
                          MessageBoxButton.OK, MessageBoxImage.Stop);
        }
    }
}


4、主题和皮肤切换

public partial class App : Application
{
    public void ChangeTheme(string themeName)
    {
        // 清除现有资源
        Resources.MergedDictionaries.Clear();
        
        // 加载新主题
        var themeUri = new Uri(#34;Themes/{themeName}.xaml", UriKind.Relative);
        var themeDict = new ResourceDictionary { Source = themeUri };
        Resources.MergedDictionaries.Add(themeDict);
        
        // 保存用户偏好
        Properties["CurrentTheme"] = themeName;
        SaveProperties();
    }
}

5、多语言/本地化支持

如果系统需要多语言,app也可以提供很好的解决思路。

public partial class App : Application
{
    public static readonly IList<string> SupportedLanguages = new List<string> { "en-US", "zh-CN" };
    
    public void ChangeLanguage(string cultureCode)
    {
        if (!SupportedLanguages.Contains(cultureCode)) return;
        
        var culture = new CultureInfo(cultureCode);
        Thread.CurrentThread.CurrentCulture = culture;
        Thread.CurrentThread.CurrentUICulture = culture;
        
        // 更新资源字典
        var dict = new ResourceDictionary();
        dict.Source = new Uri(#34;Resources/StringResources.{cultureCode}.xaml", UriKind.Relative);
        
        // 替换现有资源
        var oldDict = Resources.MergedDictionaries
            .FirstOrDefault(d => d.Source != null && d.Source.ToString().Contains("StringResources."));
        if (oldDict != null)
        {
            Resources.MergedDictionaries.Remove(oldDict);
        }
        Resources.MergedDictionaries.Add(dict);
        
        // 保存用户偏好
        Properties["CurrentLanguage"] = cultureCode;
        SaveProperties();
    }
}

6、应用程序设置持久化

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        // 加载用户设置
        LoadProperties();
        
        // 应用保存的主题
        if (Properties.Contains("CurrentTheme"))
        {
            ChangeTheme(Properties["CurrentTheme"].ToString());
        }
        
        // 应用保存的语言
        if (Properties.Contains("CurrentLanguage"))
        {
            ChangeLanguage(Properties["CurrentLanguage"].ToString());
        }
    }
    
    private void LoadProperties()
    {
        // 从隔离存储或配置文件加载
        try 
        {
            Properties = IsolatedStorageSettings.ApplicationSettings;
        }
        catch
        {
            Properties = new Hashtable();
        }
    }
    
    private void SaveProperties()
    {
        // 保存到隔离存储或配置文件
        if (Properties is IsolatedStorageSettings settings)
        {
            settings.Save();
        }
    }
    
    public Hashtable Properties { get; private set; }
}

7、单实例应用程序实现

软件开发一个很常见的需求:只能启动一个软件。也可以在app.xaml里实现。

public partial class App : Application
{
    private static Mutex _mutex;
    
    protected override void OnStartup(StartupEventArgs e)
    {
        const string appName = "MyWpfApplication";
        bool createdNew;
        
        _mutex = new Mutex(true, appName, out createdNew);
        
        if (!createdNew)
        {
            // 应用程序已经在运行
            MessageBox.Show("应用程序已经在运行中。");
            Current.Shutdown();
            return;
        }
        
        base.OnStartup(e);
    }
    
    protected override void OnExit(ExitEventArgs e)
    {
        _mutex?.ReleaseMutex();
        base.OnExit(e);
    }
}

8、启动画面(Splash Screen)实现

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        // 显示启动画面
        var splashScreen = new SplashScreen("Resources/splash.png");
        splashScreen.Show(true);
        
        // 模拟初始化耗时
        Thread.Sleep(2000);
        
        base.OnStartup(e);
    }
}

相关文章

Objective C interface(objective什么意思)

在Objective C里面,interface基本可以理解为其他语言里面的class。当然也有些不同。首先我们可以新建一个Objective-C的file。这里我们添加一个MyClass.m和一个M...

c++ 继承简介(c++继承的概念)

24.1 — 继承简介2024 年 6 月 5 日在上一章中,我们讨论了对象组合,即从更简单的类和类型构建复杂类。对象组合非常适合构建与其部分具有“has-a”关系的新对象。但是,对象组合只是 C++...

Oracle中泄露“天机”的TNS(在oracle中发出的下列查询)

数据库的安全是长期存在的问题。在目前大量的数据泄露事件以及漏洞面前,大家看到的大都是SQl注入、越权操作、缓冲区溢出等这些具体漏洞。往往却忽视了造成这些问题的前提,黑客想要入侵数据库一定会尝试获取数据...

Oracle 11g安装教程完整版(oracle 11g 安装教程)

由于工作需要,将安装的经验分享给大家。第一步:首先准备安装文件包:Oralce 11.2.0.4 64bit和plsqldev1405x64如图所示:第二步:将2个文件解压到同一个目录,如图所示:第三...

Oracle公布Java9未来进度表(oracle的未来)

作为1995年由Sun公司推出的产品,Java既是指一种程序设计语言,也包含了Java平台。因其平台无关、安全、高性能、自动垃圾回收等特点,Java已经推出便受到广泛应用。Java软件开发工具包(Ja...

Oracle-架构、原理、进程(oracle进程结构)

详解:首先看张图:对于一个数据库系统来说,假设这个系统没有运行,我们所能看到的和这个数据库相关的无非就是几个基于操作系统的物理文件,这是从静态的角度来看,如果从动态的角度来看呢,也就是说这个数据库系统...