巧用Delegate在Silverlight多个页面、控件中传递回调方法
时间:2010-08-16 来源:山天大畜
在论坛中看到经常有人碰到如何在SilverLight多个页面或者控件中传替参数或者值的问题,今天抽空通过Delegate机制实现回调实例方法重设动画参数的DEMO,分享给大家。最终结果如图:
演示地址:http://xingjunli.webs.com/DelegateDemo.html
参考资料:动画概述:http://msdn.microsoft.com/zh-cn/library/cc189019(VS.95).aspx 委托:http://msdn.microsoft.com/zh-cn/library/900fyy8e.aspx
1、初识委托:
委托delegate有点类似于非托管C/C++中的函数指针,在C#中通过委托机制来回掉实例方法,静态方法等(更重要是委托为托管代码,能保证回调方法的类型的安全)
2、使用委托回调实例方法:
2.1、用C#的delegate关键字来定义回掉函数的签名(本示例中我们通过一个单独的类来实义委托以提高重用):
view plaincopy to clipboardprint?
01./// <summary>
02. /// 声明delegate方法
03. /// </summary>
04. /// <param name="x"></param>
05. /// <param name="y"></param>
06. public delegate void delgateResetParentMethod(double x,double y);
/// <summary>
/// 声明delegate方法
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
public delegate void delgateResetParentMethod(double x,double y);
2.2、在子窗体类中我们定义一个委托类型对象如:
view plaincopy to clipboardprint?
01.public helper.delgateResetParentMethod CallBackMethod;
public helper.delgateResetParentMethod CallBackMethod;
2.3、在父窗体中实例化子窗体时将实例方法传递给委托:
view plaincopy to clipboardprint?
01.UCDelegateChildWindow childWindow = new UCDelegateChildWindow();
02. childWindow.CallBackMethod = ReaplayAnimation;
UCDelegateChildWindow childWindow = new UCDelegateChildWindow();
childWindow.CallBackMethod = ReaplayAnimation;
2.4、用我们熟悉的方法调用语法来调用回掉函数:
view plaincopy to clipboardprint?
01. if (this.DialogResult.Value && CallBackMethod != null)
02. {
03.this.CallBackMethod(Double.Parse(txtX.Text), Double.Parse(txtY.Text));
04.this.Close();
05. }
if (this.DialogResult.Value && CallBackMethod != null)
{
this.CallBackMethod(Double.Parse(txtX.Text), Double.Parse(txtY.Text));
this.Close();
}
3、上面我们应用委托实现了最简单的应用,实际工作中会复杂的多;我们的编译器和CLR为我们做了大量幕后工作以减轻使用的复杂性;如需了解更多请参考:委托(C# 编程指南)http://msdn.microsoft.com/zh-cn/library/ms173171.aspx
实现步骤(附源代码):
声明委托类型:
view plaincopy to clipboardprint?
01.public class helper
02.{
03. /// <summary>
04. /// 声明delegate方法
05. /// </summary>
06. /// <param name="x"></param>
07. /// <param name="y"></param>
08. public delegate void delgateResetParentMethod(double x,double y);
09.}
public class helper
{
/// <summary>
/// 声明delegate方法
/// </summary>
/// <param name="x"></param>
/// <param name="y"></param>
public delegate void delgateResetParentMethod(double x,double y);
}
子窗体XAML:
view plaincopy to clipboardprint?
01.<controls:ChildWindow x:Class="LoadSilverlight.UCDelegateChildWindow"
02. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
03. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
04. xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
05. Width="200" Height="170"
06. Title="重设动画坐标:">
07. <Grid x:Name="LayoutRoot" Margin="2">
08. <Grid.RowDefinitions>
09. <RowDefinition />
10. <RowDefinition Height="Auto" />
11. </Grid.RowDefinitions>
12. <Canvas Grid.Row="0" Grid.Column="0" Margin="1">
13. <Canvas.Background>
14. <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
15. <GradientStop Color="#E6E0F3F4" Offset="0"/>
16. <GradientStop Color="#FFB3BDC7" Offset="1"/>
17. </LinearGradientBrush>
18. </Canvas.Background>
19. <TextBlock Text="X:" Canvas.Left="11" Canvas.Top="8" />
20. <TextBox x:Name="txtX" Canvas.Left="28" Canvas.Top="8" Width="140" Text="100" />
21. <TextBlock Text="Y:" Canvas.Left="12" Canvas.Top="46" RenderTransformOrigin="0.417,1.375" />
22. <TextBox x:Name="txtY" Canvas.Left="28" Canvas.Top="44" Width="140" Text="100"/>
23. </Canvas>
24. <Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />
25. <Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" />
26. </Grid>
27.</controls:ChildWindow>
<controls:ChildWindow x:Class="LoadSilverlight.UCDelegateChildWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls"
Width="200" Height="170"
Title="重设动画坐标:">
<Grid x:Name="LayoutRoot" Margin="2">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Canvas Grid.Row="0" Grid.Column="0" Margin="1">
<Canvas.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#E6E0F3F4" Offset="0"/>
<GradientStop Color="#FFB3BDC7" Offset="1"/>
</LinearGradientBrush>
</Canvas.Background>
<TextBlock Text="X:" Canvas.Left="11" Canvas.Top="8" />
<TextBox x:Name="txtX" Canvas.Left="28" Canvas.Top="8" Width="140" Text="100" />
<TextBlock Text="Y:" Canvas.Left="12" Canvas.Top="46" RenderTransformOrigin="0.417,1.375" />
<TextBox x:Name="txtY" Canvas.Left="28" Canvas.Top="44" Width="140" Text="100"/>
</Canvas>
<Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1" />
<Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1" />
</Grid>
</controls:ChildWindow>
子窗体CS:
view plaincopy to clipboardprint?
01.using System;
02.using System.Collections.Generic;
03.using System.Linq;
04.using System.Net;
05.using System.Windows;
06.using System.Windows.Controls;
07.using System.Windows.Documents;
08.using System.Windows.Input;
09.using System.Windows.Media;
10.using System.Windows.Media.Animation;
11.using System.Windows.Shapes;
12.
13.namespace LoadSilverlight
14.{
15. public partial class UCDelegateChildWindow : ChildWindow
16. {
17. public UCDelegateChildWindow()
18. {
19. InitializeComponent();
20. }
21.
22. private void OKButton_Click(object sender, RoutedEventArgs e)
23. {
24. this.DialogResult = true;
25. if (this.DialogResult.Value && CallBackMethod != null)
26. {
27. this.CallBackMethod(Double.Parse(txtX.Text), Double.Parse(txtY.Text));
28. this.Close();
29. }
30.
31. }
32.
33. private void CancelButton_Click(object sender, RoutedEventArgs e)
34. {
35. this.DialogResult = false;
36. }
37.
38. //定义页面委托对象
39. public helper.delgateResetParentMethod CallBackMethod;
40.
41. }
42.}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace LoadSilverlight
{
public partial class UCDelegateChildWindow : ChildWindow
{
public UCDelegateChildWindow()
{
InitializeComponent();
}
private void OKButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
if (this.DialogResult.Value && CallBackMethod != null)
{
this.CallBackMethod(Double.Parse(txtX.Text), Double.Parse(txtY.Text));
this.Close();
}
}
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
}
//定义页面委托对象
public helper.delgateResetParentMethod CallBackMethod;
}
}
父窗体XAML:
view plaincopy to clipboardprint?
01.<UserControl x:Class="LoadSilverlight.UCDelegateParent"
02. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
03. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="#FF333333" Foreground="{x:Null}">
04. <UserControl.Resources>
05. <Storyboard x:Name="sbRun">
06. <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
07. <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
08. <EasingDoubleKeyFrame KeyTime="00:00:06" Value="200">
09. <EasingDoubleKeyFrame.EasingFunction>
10. <ElasticEase EasingMode="EaseOut"/>
11. </EasingDoubleKeyFrame.EasingFunction>
12. </EasingDoubleKeyFrame>
13. </DoubleAnimationUsingKeyFrames>
14. <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
15. <EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
16. <EasingDoubleKeyFrame KeyTime="00:00:06" Value="200">
17. <EasingDoubleKeyFrame.EasingFunction>
18. <ElasticEase EasingMode="EaseOut"/>
19. </EasingDoubleKeyFrame.EasingFunction>
20. </EasingDoubleKeyFrame>
21. </DoubleAnimationUsingKeyFrames>
22. </Storyboard>
23. </UserControl.Resources>
24. <Grid x:Name="LayoutRoot" Background="#FF424242">
25. <Ellipse x:Name="ellipse" Height="64" HorizontalAlignment="Left" Margin="25,32,0,0" VerticalAlignment="Top" Width="64" RenderTransformOrigin="0.5,0.5">
26. <Ellipse.RenderTransform>
27. <TransformGroup>
28. <ScaleTransform/>
29. <SkewTransform/>
30. <RotateTransform/>
31. <TranslateTransform x:Name="ellipseTrans"/>
32. </TransformGroup>
33. </Ellipse.RenderTransform>
34. <Ellipse.Fill>
35. <RadialGradientBrush RadiusX="0.559" RadiusY="0.559">
36. <GradientStop Color="#FFFF0606"/>
37. <GradientStop Color="#72702525" Offset="0.717"/>
38. <GradientStop Color="#00702525" Offset="1"/>
39. </RadialGradientBrush>
40. </Ellipse.Fill>
41. </Ellipse>
42. <Button x:Name="btnReset" Height="33" HorizontalAlignment="Right" Margin="0,0,8,8" VerticalAlignment="Bottom" Width="100" Content="重设坐标" FontFamily="微软雅黑" FontWeight="Bold" FontSize="18.667"/>
43. <HyperlinkButton HorizontalAlignment="Right" Margin="8,0,116,15" VerticalAlignment="Bottom" Content="http://Blog.csdn.net/xingjunli" NavigateUri="http://Blog.csdn.net/xingjunli" FontStyle="Italic"/>
44.
45. </Grid>
46.</UserControl>
<UserControl x:Class="LoadSilverlight.UCDelegateParent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Background="#FF333333" Foreground="{x:Null}">
<UserControl.Resources>
<Storyboard x:Name="sbRun">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:06" Value="200">
<EasingDoubleKeyFrame.EasingFunction>
<ElasticEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="ellipse" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<EasingDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<EasingDoubleKeyFrame KeyTime="00:00:06" Value="200">
<EasingDoubleKeyFrame.EasingFunction>
<ElasticEase EasingMode="EaseOut"/>
</EasingDoubleKeyFrame.EasingFunction>
</EasingDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="#FF424242">
<Ellipse x:Name="ellipse" Height="64" HorizontalAlignment="Left" Margin="25,32,0,0" VerticalAlignment="Top" Width="64" RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform/>
<TranslateTransform x:Name="ellipseTrans"/>
</TransformGroup>
</Ellipse.RenderTransform>
<Ellipse.Fill>
<RadialGradientBrush RadiusX="0.559" RadiusY="0.559">
<GradientStop Color="#FFFF0606"/>
<GradientStop Color="#72702525" Offset="0.717"/>
<GradientStop Color="#00702525" Offset="1"/>
</RadialGradientBrush>
</Ellipse.Fill>
</Ellipse>
<Button x:Name="btnReset" Height="33" HorizontalAlignment="Right" Margin="0,0,8,8" VerticalAlignment="Bottom" Width="100" Content="重设坐标" FontFamily="微软雅黑" FontWeight="Bold" FontSize="18.667"/>
<HyperlinkButton HorizontalAlignment="Right" Margin="8,0,116,15" VerticalAlignment="Bottom" Content="http://Blog.csdn.net/xingjunli" NavigateUri="http://Blog.csdn.net/xingjunli" FontStyle="Italic"/>
</Grid>
</UserControl>
父窗体CS:
view plaincopy to clipboardprint?
01.using System;
02.using System.Collections.Generic;
03.using System.Linq;
04.using System.Net;
05.using System.Windows;
06.using System.Windows.Controls;
07.using System.Windows.Documents;
08.using System.Windows.Input;
09.using System.Windows.Media;
10.using System.Windows.Media.Animation;
11.using System.Windows.Shapes;
12.
13.namespace LoadSilverlight
14.{
15. public partial class UCDelegateParent : UserControl
16. {
17. UCDelegateChildWindow childWindow;
18. public UCDelegateParent()
19. {
20. InitializeComponent();
21. btnReset.Click += new RoutedEventHandler(btnReset_Click);
22. sbRun.Completed += new EventHandler(sbRun_Completed);
23. this.Loaded += new RoutedEventHandler(UCDelegateParent_Loaded);
24. }
25.
26. void UCDelegateParent_Loaded(object sender, RoutedEventArgs e)
27. {
28. sbRun.Begin();
29. }
30.
31. void sbRun_Completed(object sender, EventArgs e)
32. {
33. ShowChildWindow();
34. }
35.
36. void btnReset_Click(object sender, RoutedEventArgs e)
37. {
38. ShowChildWindow();
39. }
40. private void ShowChildWindow()
41. {
42. if (childWindow == null)
43. {
44. childWindow = new UCDelegateChildWindow();
45. childWindow.CallBackMethod = ReaplayAnimation; //为子窗体(可以是任意窗体或者控件)注册父窗体实例方法(这里的参数类型和个数必须匹配)
46. }
47. childWindow.Show();
48. }
49.
50. //父窗体重设动画属性播放动画
51. private void ReaplayAnimation(double x,double y)
52. {
53.
54. DoubleAnimationUsingKeyFrames framsX = sbRun.Children[0] as DoubleAnimationUsingKeyFrames;
55. DoubleAnimationUsingKeyFrames framsY = sbRun.Children[1] as DoubleAnimationUsingKeyFrames;
56.
57. framsX.KeyFrames[0].Value = framsX.KeyFrames[1].Value;
58. framsX.KeyFrames[1].Value = x;
59. framsY.KeyFrames[0].Value = framsY.KeyFrames[1].Value;
60. framsY.KeyFrames[1].Value = y;
61.
62. sbRun.Stop();
63. sbRun.Begin();
64. }
65. }
66.}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
namespace LoadSilverlight
{
public partial class UCDelegateParent : UserControl
{
UCDelegateChildWindow childWindow;
public UCDelegateParent()
{
InitializeComponent();
btnReset.Click += new RoutedEventHandler(btnReset_Click);
sbRun.Completed += new EventHandler(sbRun_Completed);
this.Loaded += new RoutedEventHandler(UCDelegateParent_Loaded);
}
void UCDelegateParent_Loaded(object sender, RoutedEventArgs e)
{
sbRun.Begin();
}
void sbRun_Completed(object sender, EventArgs e)
{
ShowChildWindow();
}
void btnReset_Click(object sender, RoutedEventArgs e)
{
ShowChildWindow();
}
private void ShowChildWindow()
{
if (childWindow == null)
{
childWindow = new UCDelegateChildWindow();
childWindow.CallBackMethod = ReaplayAnimation; //为子窗体(可以是任意窗体或者控件)注册父窗体实例方法(这里的参数类型和个数必须匹配)
}
childWindow.Show();
}
//父窗体重设动画属性播放动画
private void ReaplayAnimation(double x,double y)
{
DoubleAnimationUsingKeyFrames framsX = sbRun.Children[0] as DoubleAnimationUsingKeyFrames;
DoubleAnimationUsingKeyFrames framsY = sbRun.Children[1] as DoubleAnimationUsingKeyFrames;
framsX.KeyFrames[0].Value = framsX.KeyFrames[1].Value;
framsX.KeyFrames[1].Value = x;
framsY.KeyFrames[0].Value = framsY.KeyFrames[1].Value;
framsY.KeyFrames[1].Value = y;
sbRun.Stop();
sbRun.Begin();
}
}
}
结束语:SilverLight同.Net FrameWork本身已经很好的结合起来,C#中一些实用的编程机制(如:委托),在SL中合理运用,将给我们带来意想不到的收获!
转载自银光中国