使用 LINQ 通过 XML 数据动态绑定 Silverlight 控件





3.00/5 (2投票s)
如何创建具有动画并与 XML 数据绑定的动态 Silverlight 控件。
引言
本文解释了如何在运行时使用 XML 绑定动态创建一个简单的 Silverlight 控件。我选择讨论一个简单的例子来演示该技术。 当然,可以根据个人需求和愿望来详细阐述该技术。
背景
在这个例子中,我们在运行时更改故事板目标,以便在创建动态控件时绑定动画,并使用 LINQ 将控件与 XML 绑定。
使用代码
我们首先创建一个 Silverlight 项目,其中包含一个简单的动画,使用 Expression Blend 使图像来回滑动。 我们使用以下代码修改 *page.xaml*
<UserControl x:Class="BindingXML.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid x:Name="LayoutRoot">
<HyperlinkButton NavigateUri=http://www.google.com TargetName="_blank"
MouseEnter="Link1_MouseEnter" MouseLeave="Link1_MouseLeave"
x:Name="Link1" Foreground="Black" Margin="8,-22,143,0"
VerticalAlignment="Top">
<Canvas>
<Image Canvas.Top="80" Canvas.Left="10"
Source="redarrow.jpg" Width="10" Height="15"
VerticalAlignment="Bottom" x:Name="image4"
RenderTransformOrigin="0.5,0.5"> </Image>
<TextBlock Canvas.Top="80" Canvas.Left="25">AskCNet</TextBlock>
</Canvas>
</HyperlinkButton>
</Grid>
</UserControl>
然后,我们在 Expression Blend 中打开 XAML 以添加所需的动画。 在此示例中,我们将向图像添加动画,使其来回滑动。 完成动画后,Expression Blend 会生成代码并将故事板添加到 XAML,并将其他代码附加到图像,如下所示
<UserControl x:Class="EurekaHomeLinks.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<Storyboard x:Name="Storyboard1" SpeedRatio="3.0">
<PointAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000"
Storyboard.TargetName="Image1"
Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)"
x:Name="samplePointAnim"> <SplinePointKeyFrame
KeyTime="00:00:00" Value="-1,0.6"/>
</PointAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Image1"
Storyboard.TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[2].(TranslateTransform.X)"
x:Name="sampleDoubleAnim1">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="-9"/>
<SplineDoubleKeyFrame KeyTime="00:00:01" Value="2"/>
<SplineDoubleKeyFrame KeyTime="00:00:02" Value="-1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Image1"
Storyboard.TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[2].(TranslateTransform.Y)"
x:Name="sampleDoubleAnim2">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:01" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard> </UserControl.Resources>
<Grid x:Name="LayoutRoot">
<HyperlinkButton NavigateUri=http://www.google.com TargetName="_blank"
MouseEnter="Link1_MouseEnter" MouseLeave="Link1_MouseLeave"
x:Name="Link1" Foreground="Black"
Margin="8,-22,143,0" VerticalAlignment="Top">
<Canvas>
<Image Canvas.Top="80" Canvas.Left="10" Source="redarrow.jpg"
Width="10" Height="15" VerticalAlignment="Bottom"
x:Name="image4" RenderTransformOrigin="0.5,0.5">
<Image.RenderTransform> <TransformGroup> <ScaleTransform/>
<SkewTransform/> <RotateTransform/> <TranslateTransform/>
</TransformGroup> </Image.RenderTransform>
</Image>
<TextBlock Canvas.Top="80" Canvas.Left="25">AskCNet</TextBlock>
</Canvas>
</HyperlinkButton>
</Grid>UserControl>
上面突出显示的代码是 Expression Blend 添加的部分。 我不会深入探讨如何在 Expression Blend 中创建动画的细节,因为这超出了本文的范围。 如果您有兴趣,请随时通过 debdatta.dey@gmail.com 给我们发邮件。
我们执行了上述步骤以从 Expression Blend 中检索故事板代码。 接下来,我们可以保留故事板并删除网格中的控件,以便我们的代码如下所示。 现在,我们将基于 XML 数据从代码隐藏中动态创建控件。 删除控件后,*page.xaml* 代码将如下所示。
<UserControl x:Class="BindingXML.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<UserControl.Resources>
<Storyboard x:Name="Storyboard1" SpeedRatio="3.0">
<PointAnimationUsingKeyFrames BeginTime="00:00:00"
Duration="00:00:00.0010000" Storyboard.TargetName="Image1"
Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)"
x:Name="samplePointAnim"> <SplinePointKeyFrame
KeyTime="00:00:00" Value="-1,0.6"/>
</PointAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Image1"
Storyboard.TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[2].(TranslateTransform.X)"
x:Name="sampleDoubleAnim1">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="-9"/>
<SplineDoubleKeyFrame KeyTime="00:00:01" Value="2"/>
<SplineDoubleKeyFrame KeyTime="00:00:02" Value="-1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="Image1"
Storyboard.TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[2].(TranslateTransform.Y)"
x:Name="sampleDoubleAnim2">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:01" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White"> </</Grid>UserControl>
接下来,我们尝试绑定到 XML 文件,并在运行时创建控件,如下所示,来自 *page.xaml.cs* 中的代码隐藏。
public Page()
{
InitializeComponent();
LoadXMLFile();
}
private void LoadXMLFile()
{
WebClient xmlClient = new WebClient();
xmlClient.DownloadStringCompleted +=
new DownloadStringCompletedEventHandler(XMLFileLoaded);
xmlClient.DownloadStringAsync(new Uri("MainPageLinks.xml",
UriKind.RelativeOrAbsolute));
}
加载 XML 文件后,我们使用 LINQ 构建与 XML 数据绑定的控件,如下所示
void XMLFileLoaded(object sender, DownloadStringCompletedEventArgs e)
{
double initialTextLeft = 25;
double initialImageLeft = 10;
double initialTop = 40;
Thickness thickButton = new Thickness();
thickButton.Left = 8;
thickButton.Top = -22;
thickButton.Right = 143;
thickButton.Bottom = 0;
Point pointImageTransformOrigin = new Point();
pointImageTransformOrigin.X = 0.5;
pointImageTransformOrigin.Y = 0.5;
if (e.Error == null)
{
string xmlData = e.Result;
XDocument xdoc = XDocument.Parse(xmlData);
var linkItems = from b in xdoc.Descendants() where b.Name == "Link"
select b;
foreach (XElement link in linkItems)
{
string linkText = link.Element("Text").Value;
string URL = link.Element("URL").Value;
string No = link.Attribute("No").Value;
Canvas sampleCanvas = new Canvas();
Image sampleImage = new Image();
sampleImage.Source = new BitmapImage(new Uri("pencil.jpg", UriKind.Relative));
sampleImage.VerticalAlignment = VerticalAlignment.Bottom;
sampleImage.SetValue(Canvas.LeftProperty, initialImageLeft);
sampleImage.SetValue(Canvas.TopProperty, initialTop);
sampleImage.SetValue(NameProperty, "Image" + No);
sampleImage.RenderTransformOrigin = pointImageTransformOrigin;
TransformGroup imgTransGroup = new TransformGroup();
ScaleTransform imgScale= new ScaleTransform();
RotateTransform imgRotate = new RotateTransform();
TranslateTransform imgTranslate = new TranslateTransform();
SkewTransform imgScew = new SkewTransform();
imgTransGroup.Children.Add(imgScale);
imgTransGroup.Children.Add(imgRotate);
imgTransGroup.Children.Add(imgTranslate);
imgTransGroup.Children.Add(imgScew);
sampleImage.RenderTransform = imgTransGroup;
TextBlock sampleText = new TextBlock();
sampleText.Text = linkText;
sampleText.SetValue(Canvas.LeftProperty, initialTextLeft);
sampleText.SetValue(Canvas.TopProperty, initialTop);
sampleCanvas.Children.Add(sampleImage);
sampleCanvas.Children.Add(sampleText);
HyperlinkButton sampleButton = new HyperlinkButton();
sampleButton.TargetName = "_blank";
sampleButton.NavigateUri = new Uri(URL);
sampleButton.VerticalAlignment = VerticalAlignment.Top;
sampleButton.Foreground = new System.Windows.Media.SolidColorBrush(Colors.Black);
sampleButton.MouseEnter += new MouseEventHandler(sampleButton_MouseEnter);
sampleButton.MouseLeave += new MouseEventHandler(sampleButton_MouseLeave);
sampleButton.SetValue(NameProperty, "Button" + No);
sampleButton.Margin = thickButton;
sampleButton.SetValue(Canvas.LeftProperty, initialTextLeft);
sampleButton.SetValue(Canvas.TopProperty, initialTop);
initialTop += 20;
sampleButton.Content = sampleCanvas;
this.LayoutRoot.Children.Add(sampleButton);
}
}
}
在以下代码中,我们通过将故事板的目标附加到 HyperLinkButton
内的图像,来启动 HyperLinkButton
的 OnMouseEnter
故事板。 此外,我们还使获得鼠标事件的 HyperLinkButton
的 TextBlock
变为粗体。 在 OnMouseLeave
中,我们将 TextBlock
的字体粗细设置回正常并停止故事板。
private void sampleButton_MouseLeave(object sender, MouseEventArgs e)
{
HyperlinkButton linkControl = new HyperlinkButton();
linkControl = (HyperlinkButton)sender;
linkControl.FontWeight = FontWeights.Normal;
Storyboard1.Stop();
}
private void sampleButton_MouseEnter(object sender, MouseEventArgs e)
{
String controlNo = "0";
HyperlinkButton linkControl = new HyperlinkButton();
linkControl = (HyperlinkButton)sender;
linkControl.FontWeight = FontWeights.Bold;
controlNo = linkControl.Name.Substring(6, linkControl.Name.Length - 6);
samplePointAnim.SetValue(Storyboard.TargetNameProperty, "Image" + controlNo);
sampleDoubleAnim1.SetValue(Storyboard.TargetNameProperty, "Image" + controlNo);
sampleDoubleAnim2.SetValue(Storyboard.TargetNameProperty, "Image" + controlNo);
Storyboard1.Begin();
}
关注点
您可能想知道为什么我没有使用图像,然后使用 HyperLinkButton
,而不是使用图像和 HyperLinkButton
控件中的 TextBlock
。 我选择这样做主要是因为我不想要鼠标悬停在 HyperLinkButton
上时出现的下划线。 CSS 修改实际上不起作用。 设置 HyperLinkButton
的边距消除了使用超链接创建的难看的蓝色框 (margin ="8,-22,143,0" )。
最后,请让我知道您对本文的想法。 谢谢!
历史
- 刚刚创建。 到目前为止还没有。