使用观察者模式在 Silverlight 中切换用户控件

有一篇技巧,见

http://tech.sina.com.cn/s/2008-07-03/1528718607.shtml

http://kb.cnblogs.com/page/42897/?page=1

讨论的是运用InitParams在Silverlight 2应用程序中切换用户控件,这是个很笨但是直观的解决方式。

但如果在控件中传值,那将怎么办?以上方法将毫无用途!

今天在一个老外的博客看到有个很巧妙的方法,不敢独享,现分享出来:

首先写个接口:


namespace PageSwitchSimple
{
  public interface ISwitchable
  {
    void UtilizeState( object state );
  }
}

然后写个切换类:

using System.Windows.Controls;

namespace PageSwitchSimple
{
  public static class Switcher
  {
    public static PageSwitcher pageSwitcher;

    public static void Switch( UserControl newPage )
    {
      pageSwitcher.Navigate( newPage );
    }

    public static void Switch( UserControl newPage, object state )
    {
      pageSwitcher.Navigate( newPage, state );
    }
  }
}

PageSwitcher 成员类:

前台代码:

<UserControl x:Class="PageSwitchSimple.PageSwitcher"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="800" Height="600">

</UserControl>

后台代码:

using System;
using System.Windows.Controls;

namespace PageSwitchSimple
{
  public partial class PageSwitcher : UserControl
  {
    public PageSwitcher()
    {
      InitializeComponent();
    }

    public void Navigate( UserControl nextPage )
    {
      this.Content = nextPage;
    }

    public void Navigate( UserControl nextPage, object state )
    {
      this.Content = nextPage;
      ISwitchable s = nextPage as ISwitchable;

      //这里真是太巧妙了,用于传object 参数!
      if ( s != null )
      {
        s.UtilizeState( state );
      }
      else
      {
        throw new ArgumentException( "nextPage is not ISwitchable! "
          + nextPage.Name.ToString() );
      }
    }
  }
}


 

然后写两个实现接口ISwitchable的用户控件:

控件一:

<UserControl x:Class="PageSwitchSimple.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
  <Grid x:Name="LayoutRoot" Background="White">
    <TextBlock Text="Your Name: " FontSize="18" />
    <TextBox x:Name="Name" FontSize="18" Width="150" Height="35" VerticalAlignment="Top" Margin="5"/>
    <Button x:Name="ChangePage" Content="Change" FontSize="18" Width="100" Height="50" />
  </Grid>
</UserControl>


 

后台代码:

using System.Windows;
using System.Windows.Controls;

namespace PageSwitchSimple
{
  public partial class Page : UserControl, ISwitchable
  {
    public Page()
    {
      InitializeComponent();
      ChangePage.Click += new RoutedEventHandler( ChangePage_Click );
    }

    void ChangePage_Click( object sender, RoutedEventArgs e )
    {
      Switcher.Switch( new Page2(), Name.Text );
    }
  }
}

控件二:

<UserControl x:Class="PageSwitchSimple.Page2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="400" Height="300">
  <Grid x:Name="LayoutRoot" Background="Bisque">
    <TextBlock x:Name="Message" Text="Page2" FontSize="18" />
    <Button x:Name="ChangePage" Content="Change" FontSize="18" Width="100" Height="50" />
  </Grid>
</UserControl>


 

后台代码:

using System.Windows;
using System.Windows.Controls;

namespace PageSwitchSimple
{
  public partial class Page2 : UserControl, ISwitchable
  {
    public Page2()
    {
      InitializeComponent();
      ChangePage.Click += new RoutedEventHandler( ChangePage_Click );
    }

    public void UtilizeState( object state )
    {
      Message.Text = state.ToString();
    }

    void ChangePage_Click( object sender, RoutedEventArgs e )
    {
      Switcher.Switch( new Page() );
    }
  }
}

最后修改App.cs

    private void Application_Startup( object sender, StartupEventArgs e )
    {
      PageSwitcher pageSwitcher = new PageSwitcher();
      this.RootVisual = pageSwitcher;
      Switcher.pageSwitcher = pageSwitcher;
      Switcher.Switch( new Page() );
    }

巧妙运用了观察者模式,佩服作者的思路。

 

关于作者: 王昕(QQ:475660) 在广州工作生活30余年。十多年开发经验,在Java、即时通讯、NoSQL、BPM、大数据等领域较有经验。
目前维护的开源产品:https://gitee.com/475660
原文地址:https://www.cnblogs.com/starcrm/p/1520714.html