【WPF】关于窗体继承(二) – Window.ApplyTemplate()

前文说道,界面的继承一种做法是通过用户控件,而另一种做法没提到,就是通过样式模板来实现继承。

 

考虑一番,觉得还是后一种方法要简单实用,所以我决定采用它。

 

对于该方法的实现,我主要参考的是周银辉的文章 [WPF疑难] 继承自定义窗口

 

按照密籍练了一番之后,发现主要的问题集中在基类窗体的InitializeEvent()方法(该方法可在上面链接的页面的源码中找到),该方法主要实现在窗体运行时,从资源文件中找到控件模板应用后的最大化、最小化按钮等模板定义的控件的实例,然后添加为它们添加事件。

 

 protected void InitializeEvent()
        {
            try
            {
                ControlTemplate baseWindowTemplate = (ControlTemplate)this.Resources["WindowBaseUI"];

                JelloImage minBtn = (JelloImage)baseWindowTemplate.FindName("BtMin", this);
                minBtn.MouseLeftButtonUp += delegate
                {
                    this.WindowState = WindowState.Minimized;
                };

                JelloImage maxBtn = (JelloImage)baseWindowTemplate.FindName("BtMax", this);
                maxBtn.MouseLeftButtonUp += delegate
                {
                    this.WindowState = (this.WindowState == WindowState.Normal ? WindowState.Maximized : WindowState.Normal);
                };
 
这个方法的调用时机有讲究,因为控件生存周期是有讲究的。
原先该方法我放在基实窗体的构造函数中,结果,baseWindowTemplate 可以取到,但minBtn始终取不到。
后来考虑到可能是生存周期问题,就把该方法的调用放到窗体的Loaded事件中,结果成功取得minBtn.
 
原以为这样就OK了,谁知…..
我在继承基类窗体的子窗体上放置了两个按钮,用于切换两个皮肤。

private void button1_Click(object sender, RoutedEventArgs e)
{
    this.InitializeStyle("Skin1");
}

private void button2_Click(object sender, RoutedEventArgs e)
{
    this.InitializeStyle("Skin2");
}

一点,钢钢的,皮肤换了,爽啊,呵呵,可是,且慢,最大化、最小化按钮不干活了。噢,应该是换肤后要再调一下InitializeEvent()方法,立马加上。
private void button1_Click(object sender, RoutedEventArgs e)
        {
          
            this.InitializeStyle("Skin1");
            
            this.InitializeEvent();
          
        }

        private void button2_Click(object sender, RoutedEventArgs e)
        {
            this.InitializeStyle("Skin2");
            this.InitializeEvent();
        }

再运行,我点…完了,又是baseWindowTemplate 可以取到,但minBtn始终取不到,真是怀具啊。
为啥子哩,闷了好几天。
 
今天大大方便时,闲来无事突然想到,既然InitializeEvent放在窗体的Loaded事件中可以成功执行,那我在换肤后,先调一下窗体的Loaded事件,然后再调InitializeEvent岂不是就应该就可以了吗?
回去后,急迫的打开工程,准备写下(this as Window).OnLoad,可是,没有OnLoad! 靠,要是PB就好了,我马上Event! 
我马上想到是不是窗体还是别的方法来应用模板,果然黄天不负苦心人,立马在智能感应列表中找到一个好像好像的方法
ApplyTemplate()
,应用,大功告成。
最终,我把该方法放在了基类窗本的InitializeStyle中.
 protected void InitializeStyle(string skinname)
        {
            try
            {
                if (this.Resources.MergedDictionaries.IndexOf(this.SkinResource) >= 0)
                {
                    this.Resources.MergedDictionaries.Remove(SkinResource);
                }

                SkinResource.Source = new Uri("pack://application:,,,/Test;component/Resources/" + skinname + "/StyleDictionary.xaml");

                this.Resources = SkinResource;
                this.Style = this.FindResource("BaseWindowStyle") as Style;
               
               this.ApplyTemplate();
            }
            catch(Exception Ex)
            {
                MsgHelper.ShowExceptionMessge(this.Title, "加载样式失败", Ex);
            }
           
        }

注:好多次在大大方便得到很犀利很犀利的方法,哈哈,天助我也!
 
 
 
 
 

posted on 2010-03-23 16:59  Apollo Sun  阅读(3725)  评论(0编辑  收藏  举报

导航