WPF工作笔记:本地化支持、主线程通知、

1、本地化支持

(1)覆盖控件默认的依赖属性LanguageProperty

FrameworkElement.LanguageProperty.OverrideMetadata(
                typeof(FrameworkElement), new FrameworkPropertyMetadata(
                    XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));

(2)在项目资源文件中添加Resources.resx,Resources.zh-CN.resx等等本地化字符串资源。

文件中依次输入Key-Value键值对,key相同,Value中输入本地化语言字符串,如下所示

(3)在界面中引用命名空间。如:

xmlns:resc="clr-namespace:WpfApplication.Resources"

(4)引用资源字符串资源。如 :

<Button Content="{x:Static resc:Resources.Open}"/>

2、主进程通知

在多文件支持和音视频播放界面应用中,经常需要在外部通知主进程。比如您已经打开了酷狗音乐播放界面,在外部文件夹中,双击.mp3音乐文件,不会启动第二个酷狗音乐播放界面,而是通知主窗口接收外部请求。下面给出一种实现方式:

首先声明WPF开发的系统只有一个入口,那就是Application类,也就是App.xaml

(1)App.xaml中不需要StartupUri,在后台启动主窗口。首先在App.xaml.cs中定义事件句柄,用于通知主窗口

public static EventWaitHandle ProgramStarted;
private bool CreatedNew;

(2)App.xaml.cs重写OnStartup,判断是否需要新建主窗口

ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, "MyStartEvent", out CreatedNew);

通过上面语句得到的CreatedNew值来决定是否需要创建主窗口,CreatedNew等于true时按一般情况声明主窗口:

if (CreatedNew)
{
      MainWindow mainWin = new MainWindow();
      mainWin.Show();
}

(3)下面才是重点,在主窗口已经启动的情况下,如何将外部的文件传递到主窗口去

因为前面已经定义了事件句柄ProgramStarted,我们首先需要将外部文件写入到一个本地文件或者注册表中(名其为Global),已经启动的窗口进程得到通知后,去读取新建App进程写入的内容。

然后调用ProgramStarted.Set();Thread.Sleep(100);主窗口就可以得到通知。

(4)主窗口的线程池中需要注册Wait请求:

MainWindow.xaml.cs构造函数中:

ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);

事件回调处理函数:

        /// <summary>
        /// 主进程在接收到其他进程通知后回调函数
        /// </summary>
        /// <param name="state"></param>
        /// <param name="timeout"></param>
        private void OnProgramStarted(object state, bool timeout)
        {
            Thread thread = new Thread(new ThreadStart(new Action(() =>
            {
                this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (System.Threading.ThreadStart)delegate()
                {
                    //处理Global
                });
            })));
            //因为是线程池通知主进程,必须在单线程单元ApartmentState.STA执行
            thread.SetApartmentState(ApartmentState.STA);
            thread.IsBackground = true;
            thread.Start();
        }

  注意上面代码中使用了Dispatcher,只有WPF这样使用,能够访问主窗口控件,因为主窗口控件所在的线程是主窗口,不能在新建的线程中调用,如果要使用,需要使用Dispatcher。

默认Dispatcher执行的环境也是ApartmentState.STA,所以上面的代码可以简单为(只能在WPF中可以这样使用):

        private void OnProgramStarted(object state, bool timeout)
        {
                this.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, (System.Threading.ThreadStart)delegate()
                {
                   //处理Global
                });
        }

  

时间: 2024-10-23 04:59:43

WPF工作笔记:本地化支持、主线程通知、的相关文章

Android 在工作线程(非主线程)更改UI组件

Looper.prepare();          Toast.makeText(LoginActivity.this,filedId, Toast.LENGTH_LONG).show();        Looper.loop(); 这样为什么可以?然后就是loop 是个死循环,这样子真的好吗?

Android:子线程向UI主线程发送消息

在Android里,UI线程是不允许被阻塞的,因此我们要将耗时的工作放到子线程中去处理. 那么子线程耗时处理后要怎样通知UI线程呢? 我们可以在UI主线程中创建一个handler对象,然后通过重写其handleMessage(Message msg)的方法,该方法会接收到子线程中的handler对象的sendMessage((Message msg)发回来的消息.这样一发一收就完成工作: 而关于主线程向子线程发送消息的内容可以看我的上一篇博客,其中讲到了Looper类及其两个重要方法和实现原理.

线程通信之looper之用法--主线程和工作线程

说明:(之前只用handle是因为主线程默认就加上Looper.prepare()和Looper.loop()的.所以主线程可以通过handle收发信息,但是如果在thread里面的话,就是工作线程,工作线程的话,默认是没有加上那两段代码的,所以要手动加上,然后再通过handle.sendMessage()发送信息到工作线程才能取到信息) 主显示布局以及代码: activity_main.xml: <LinearLayout xmlns:android="http://schemas.an

C#子线程执行完后通知主线程(转)

其实这个比较简单,子线程怎么通知主线程,就是让子线程做完了自己的事儿就去干主线程的转回去干主线程的事儿.  那么怎么让子线程去做主线程的事儿呢,我们只需要把主线程的方法传递给子线程就行了,那么传递方法就很简单了委托传值嘛: 下面有一个例子,子线程干一件事情,做完了通知主线程 public class Program { //定义一个为委托 public delegate void Entrust(string str); static void Main(string[] args) { Ent

解决定时器在主线程不工作问题

有时候在主线程执行一些操作的时候,定时器会被卡死,比如来回滚动和点击屏幕处理一些主线程事务时, 就是说主界面有UITableView或者UIScrollView,滑动UITableView或者UIScrollView.这个时候NSTimer失效了. NSTimer *timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(someAction) userInfo:nil repeats:YES]; 解决方法就

Android笔记(三十二) Android中线程之间的通信(四)主线程给子线程发送消息

之前的例子都是我们在子线程(WorkerThread)当中处理并发送消息,然后在主线程(UI线程)中获取消息并修改UI,那么可以不可以在由主线程发送消息,子线程接收呢?我们按照之前的思路写一下代码: package cn.lixyz.handlertest; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import andr

【Android笔记】不能在主线程中进行网络操作

在网上看到,自己以前也曾经遇到: 1 04-26 14:36:14.663: E/AndroidRuntime(10368): android.os.NetworkOnMainThreadException 2 04-26 14:36:14.663: E/AndroidRuntime(10368): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117) 3 但是我在manifest里配置了

c#子线程执行完怎么通知主线程(转)

定义一个委托实现回调函数 public delegate void CallBackDelegate(string message); 程序开始的时候 //把回调的方法给委托变量 CallBackDelegate cbd = CallBack; //启动线程 Thread th = new Thread(Fun); th.Start(cbd);//开始线程,代入参数 //线程执行的方法 参数是个委托, 线程中参数需要用object类型. public void Fun(object o) { /

详解UIKit框架:它所定义的iOS主线程执行流程

如果我们使用模板来新建一个project,比如Master Detail Application或者tabbed Application之类,那么Xcode将会为我们自动生成Main.storyboard文件,这样一来那些本来实在源代码中间中被定义的线程执行流程,现在全部在这个故事版文件中被定义了.用故事版当然有故事版的好处,只能用来定义的可视化元素现在允许程序员用可视化的方式来定义,不过对于并不是非常熟悉iOS编程的程序员来说,这种搭建UI的方式并不利于维护修改,因为程序员不容易看到线程的实际