65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (2投票s)

2009年3月9日

CPOL

2分钟阅读

viewsIcon

42010

downloadIcon

459

如何创建具有动画并与 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 内的图像,来启动 HyperLinkButtonOnMouseEnter 故事板。 此外,我们还使获得鼠标事件的 HyperLinkButtonTextBlock 变为粗体。 在 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" )。

最后,请让我知道您对本文的想法。 谢谢!

历史

  • 刚刚创建。 到目前为止还没有。
© . All rights reserved.