了解ASP.NET 众所周网页间传递值大都用Session内部对象来应用的(比较安全方面考虑),但silverlight窗体作为承载于ASP.NET应用的程序似乎无法用与Session类似的方法了,怎么办呢?今天测试了两个小程序供参考。

示例1(从子窗体传值给父窗体)

1.新建一个silverlight项目用web程序承载它;

2.然后新建一个子窗体控件ChildWindow命名为ChildWindowDemo.xaml;

3.在ChildWindowDemo.xaml中添加一个TextBox控件,命名为tbchildinfo(如图)

ChildWindowDemo.xaml文件如下:

<basics:ChildWindow 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
              xmlns:basics="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls" 
              x:Class="PassInfo.ChildWindowDemo" 
              Title="ChildWindowDemo" 
              ;400" Height="300"> 
<Grid x:Name="LayoutRoot" Background="White"> 
<Grid.RowDefinitions> 
<RowDefinition /> 
<RowDefinition Height="Auto" /> 
</Grid.RowDefinitions> 
<Button x:Name="OKButton" Content="OK" Click="OKButton_Click" ;75" Height="23" HorizontalAlignment="Right" Grid.Row="1" /> 
<Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" ;75" Height="23" HorizontalAlignment="Right" Margin="0,0,79,0" Grid.Row="1" /> 
<TextBox x:Name="tbchildinfo" Margin="98,81,89,0" VerticalAlignment="Top" Text="TextBox" TextWrapping="Wrap"/> 
</Grid> 
</basics:ChildWindow>

4.在子窗体后台代码中添加一个字符串的属性和字段(用来保存子窗体输入的了字符串值)代码如下:

        public string childString; 
public string ChildString 
        { 
get { return childString; } 
set { childString = value; } 
        }

5.在子窗体中的后台代码中创建一个EventHandle事件控制器(使父窗体能够用这个控制器获取子窗体中的的childString参数):

public event EventHandler OkClicked;

6.子窗体如图:

用OK 按钮来确认输入的TextBox值,事件代码如下:

private void OKButton_Click(object sender, RoutedEventArgs e) 
        { 
//this.DialogResult = true; 
if (OkClicked != null) 
            { 
                childString = this.tbchildinfo.Text; 
                OkClicked(this, new EventArgs());//设置事件控制器是子容口ChildWindowDemo.xaml本身所定义; 
            } 
this.DialogResult = true; 
       }

7.此时的ChildWindowDemo..xaml.cs代码如图:

8.在父窗体中添加一个TextBox文本框和一个按钮,并且添加相应的单击事件,MainPage.xaml代码如下:

<UserControl x:Class="PassInfo.MainPage" 
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
   mc:Ignorable="d" d:Design;640" d:DesignHeight="480"> 
<Grid x:Name="LayoutRoot"> 
<Grid Margin="220,208,121,114"> 
<TextBox x:Name="tbinfo" Margin="4,5,7,0" Text="getstring" TextWrapping="Wrap" VerticalAlignment="Top" HorizontalAlignment="Center" ;196" d:LayoutOverrides="VerticalAlignment" Height="34"/> 
<Button x:Name="btPopup" Click="btPopup_Click" Margin="0,76,65,46" Content="showChild" HorizontalAlignment="Right" ;79"/> 
</Grid> 
</Grid> 
</UserControl>

窗体如图所示:

9.接下来处理父窗体调用子窗体的事件,首先在父窗体中定义子窗体对象:

private ChildWindowDemo childwindowdemo = new ChildWindowDemo();

10.MainPage.xaml窗体通过子窗体创建的事情控制器OkClicked可以调用子窗体的OkClicked事情,此事件包含子窗体的OKButton_Click 事件信息,如图:

11.通过单击showchild按钮来弹出子窗体输入信息。

12.结果如图:

示例2(从父窗体中传值给子窗体)

我们打开一个子窗体往往要从父窗体中获取某个参数(比如获取登录时的用户名),其实在silverlight程序中这种传值机制就好比是将事情发生的具体情况告诉给所要调查事件经过的对象(子窗体)。实现过程不会与示例1相反(我试验过用示例1相反的思路来做行不通), 其实本示例这种方法可替代示例1,也可用来做窗体跳转(多功能)。

用什么方法?下面介绍一种非常科学的结构来实现(主要是实现外部类的调用与接口的实现及方法的重载),此方法可实现三种界面(UserControl、Page、ChildWindow)窗体实现值互传。如下:

1.新建silverlight项目用WEB应用承载,用Blend分别添加一个子Page命名为Page1.xaml和一个ChildWindow命名为ChildWindows.xaml,在VS2008中添加两个类文件分别命名为Pass.cs和IPass.cs(用来新建接口),如图:

2.新建的两个窗体显示效果如下:

Page1.xaml窗体

ChildWindows.xaml窗体

3.修改IPass.cs文件中的类,将其作为接口来用,添加如下代码:

public interface IPass


void MyUtilizeState(object state); 
}

IPass.cs文件代码如图:

4.不需要对MainPage.xaml添加任务控件(当然你也可以修改名称),修改MainPage.xaml.cs,添加2*3个Navigator方法,每两个Navigator方法对应一种用户控件,这里重载了Navigator方法,使它可以征对不同的父子窗体实现值互传递,代码如下:

public partial class MainPage : UserControl 
    { 
public MainPage() 
        { 
            InitializeComponent(); 
        } 
//打开的第一个页面是UserControl 
public void Navigator(UserControl newpage) 
        { 
this.Content = newpage; 
        } 
//重载就可以传值了 
public void Navigator(UserControl newpage, object state) 
        { 
this.Content = newpage; 
            IPass p = newpage as IPass;//打开的第一个页面作为接口 
if (p != null) 
            { 
                p.MyUtilizeState(state); 
            } 
else 
            { 
throw new ArgumentException("不具有傳遞值的頁面" 
+ newpage.Name.ToString()); 
            } 
        } 
//打开的第一个页面是Page 
public void Navigator(Page newpage) 
        { 
this.Content = newpage; 
        } 
public void Navigator(Page  newpage, object state) 
        { 
this.Content = newpage; 
            IPass p = newpage as IPass; 
if (p != null) 
            { 
                p.MyUtilizeState(state); 
            } 
else 
            { 
throw new ArgumentException("不具有傳遞值的頁面" 
+ newpage.Name.ToString()); 
            } 
        } 
//打开的第一个页面是ChildrenWindow 
public void Navigator(ChildWindow  newpage) 
        { 
this.Content = newpage; 
        } 
public void Navigator(ChildWindow  newpage, object state) 
        { 
this.Content = newpage; 
            IPass p = newpage as IPass; 
if (p != null) 
            { 
                p.MyUtilizeState(state); 
            } 
else 
            { 
throw new ArgumentException("不具有傳遞值的頁面" 
+ newpage.Name.ToString()); 
            } 
        } 
}

 

5.修改Pass.cs文件,首先创建一个MainPage对象,但不用实例化:

public static MainPage mp;

6.接下来在Pass.cs文件中对MainPage.xaml.cs中定义的六个方法抽象地实现(之所以要用此文件来对MainPage.xaml.cs中的六个方法抽象实现是为了提供一个公共的外部类使任何需要传值的窗体之间建立关系而已),代码如下:

7.现在已经部署好了接口与方法,接下来就可以随意在窗体中调用Pass.cs中的方法了(只需要在Pass.Mypass(UserControl,object) 方法中将UserControl换成子窗体的new对象就OK)。在此要实现的是将父窗体Page1.xaml中文本框tbsetstring的值传递给ChildWindows.xaml并在ChildWindows.xaml的文本框中显示,非常简单,先实现Page1.xaml及其后台代码Page.xaml.cs,如下:

这边单击btshowchild按钮后调用Pass类的Mypass()方法实现 跳转与传值。

8.目的是要在ChildWindows.xaml窗体中显示其父窗体Page1.xaml传来的值,所以接下来修改ChildWindows.xaml和后台代码ChildWindows.xaml.cs,如下:

要注意的是对接口IPass的实现,因为接口中定义的就是窗体控件的值,而此页面就是为了获取这个值。所以实现接口方法并将最终结果显示在ChildWindows.xaml的tbgetstring文本框中。

9.最后一步要修改的是App.xaml.cs文件,只需要将Application_Startup事件委托中设置第一个加载的页面就OK了(这里第一个加载的页面是Page1.xaml),代码如下:

private void Application_Startup(object sender, StartupEventArgs e)

        { 
            MainPage mp = new MainPage(); 
this.RootVisual = mp; 
            Pass.mp = mp; 
            Pass.Mypass(new Page1()); 
        }

最终结果不是很完美,是因为这么好的方法用在这么一个简单的示例中,有点杀鸡用牛刀了。运行结果如下所示:

OK搞定。