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

Silverlight 4:如何创建自定义 OOB 窗口?

2010 年 3 月 27 日

CPOL

6分钟阅读

viewsIcon

51935

downloadIcon

369

在本文中,我将指导您在 Silverlight 4 RC 中创建一个简单的自定义 OOB 窗口应用程序。完成本教程后,您将能够创建 Silverlight 4 中的自定义 OOB 窗口。

引言

正如大家所知,Silverlight 中的“脱离浏览器”(Out-Of-Browser, OOB)功能并不是一项新功能,它自 Silverlight 3 起就已可用。微软在 Silverlight 4 Beta 中添加了受信任应用程序行为。除此之外,他们还在 Silverlight 4 RC(发布候选版)中引入了另一项附加功能,称为“无边框 OOB 窗口”,即“自定义 OOB 窗口”。在本帖中,我将指导您在 Silverlight 4 RC 中创建一个简单的自定义 OOB 窗口应用程序。完成本教程后,您将能够创建 Silverlight 4 中的自定义 OOB 窗口,其外观将类似于此。

image

背景

在 Silverlight 4 RC 之前,您可以将 Silverlight 应用程序安装在浏览器窗口之外并从桌面运行它,但无法自定义窗口的外观和感觉。从现在开始,它具备了创建自定义边框窗口以匹配应用程序 UI 的功能。在 Silverlight 4 RC 之前,您的 OOB 应用程序看起来应该像这样。

image

先决条件

要开发这个简单的应用程序,您需要在开发环境中安装以下工具

  • Visual Studio 2010 Release Candidate
  • 适用于 Visual Studio 2010 Release Candidate 的 Silverlight 4 Release Candidate 工具

请记住,Silverlight 4 应用程序只能在 Visual Studio 2010 中开发。因此,如果您的 PC 上安装了 Visual Studio 2008,您可以并排安装 Visual Studio 2010 来探索 Silverlight 4。

入门

如果您的开发环境已准备就绪,那么我们可以继续创建一个新的 Silverlight 应用程序项目。在本文档的最后,我们将能够在浏览器内运行我们的第一个 Silverlight 应用程序。

  1. 打开您的 Visual Studio 2010 IDE
  2. 选择“文件”>“新建项目”或直接按 CTRL + SHIFT + N 打开“新建项目”对话框
  3. 展开“Visual C#”节点,然后转到子节点“Silverlight”
  4. 在右侧窗格中选择“Silverlight 应用程序”
  5. 选择一个合适的存储应用程序的位置(例如,“D:\Sample Apps\”)。
  6. 现在为您的项目输入一个合适的名称(称之为:“Silverlight4.OOB.ChromelessWindow.Demo”)。
  7. 从顶部的组合框中选择 .NET Framework 版本(我使用的是 .NET Framework 4.0)
  8. 单击“确定”继续
  9. 在下一个对话框中,确保选择了“在新的网站中承载 Silverlight 应用程序”选项
  10. 选择“Silverlight 4”作为 Silverlight 版本,然后点击“确定”

稍等片刻,Visual Studio 将为您创建一个 Silverlight 解决方案,其中包含一个 Silverlight 项目和一个用于托管 Silverlight 应用程序的 Web 应用程序项目。在您的 Silverlight 项目中,您会找到由 IDE 模板为您创建的“MainPage.xaml”和“App.xaml”文件。

设计自定义边框窗口 XAML

作为第一步,为了实现自定义窗口的外观和感觉,我们需要创建一个包含窗口标题、最大化、最小化和关闭按钮的“ControlBar”。为此,让我们在 Silverlight 项目中创建一个 UserControl(虽然使用 CustomControl 会更好,但我这里使用 UserControl 是为了提供一种简单的理解主要原理的方法),并将其命名为“ControlBar”。

这是 ControlBar 的一个简单设计,它包含一个作为 TextBlock 的标题,以及作为 Border 包裹在 Canvas 中的最小化、最大化和关闭按钮。

<Grid x:Name="grdControlBarRoot" Margin="0,0,0,0">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="15"/>
        <ColumnDefinition Width="*"/>
        <ColumnDefinition Width="100"/>
    </Grid.ColumnDefinitions>
    <Border Margin="0,0,0,0" Grid.ColumnSpan="3" Background="Black" Height="25"/>
    <TextBlock HorizontalAlignment="Left" Margin="0,0,5,0" VerticalAlignment="Center" 
               Grid.Column="1" Text="{Binding Title, ElementName=userControl}" 
               TextWrapping="Wrap" FontWeight="Normal" 
	      Foreground="White" x:Name="txbTitle" 
               FontSize="12"/>
    <StackPanel x:Name="stpControlBarRoot" Grid.Column="2" Orientation="Horizontal" 
                Margin="0,0,0,0" HorizontalAlignment="Right">
        <Canvas Width="30" x:Name="cnvMinimizeButton" 
		Cursor="Hand" Background="#00000000" 
                	Visibility="Visible" Height="20" ToolTipService.ToolTip="Minimize">
            <Border Width="30" Height="20" Background="#FF939393" 
		BorderBrush="#FF000000" 
                    BorderThickness="1,1,0,1" CornerRadius="0,0,0,5">
                <Border BorderThickness="1.5,1.5,1.5,1.5" CornerRadius="0,0,0,5">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.514,0.623" 
                                             StartPoint="0.514,0.191">
                            <GradientStop Color="#FF828282" Offset="0"/>
                            <GradientStop Color="#FF262626" Offset="1"/>
                        </LinearGradientBrush>
                    </Border.Background>
                    <Rectangle Margin="6,9,6,3" Fill="#FFD6D5D5" Stroke="#FF000000" 
                               StrokeThickness="0.5"/>
                </Border>
            </Border>
        </Canvas>
        <Canvas Width="30" x:Name="cnvMaximizeButton" 
		Cursor="Hand" Background="#00000000" 
                	Visibility="Visible" Height="20" ToolTipService.ToolTip="Maximize">
            <Border Width="30" Height="20" Background="#FF939393" 
		BorderBrush="#FF000000" 
                    BorderThickness="1,1,0,1">
                <Border BorderThickness="1.5,1.5,1.5,1.5" 
		      CornerRadius="0,0,0,0" Width="29" 
                        Height="18">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.514,0.623" 
                                             StartPoint="0.514,0.191">
                            <GradientStop Color="#FF828282" Offset="0"/>
                            <GradientStop Color="#FF262626" Offset="1"/>
                        </LinearGradientBrush>
                    </Border.Background>
                    <Border Background="#FFD6D5D5" Margin="6,2,6,2" 
			BorderBrush="#FF000000" 
                           	BorderThickness="0.5,0.5,0.5,0.5">
                        <Rectangle Stroke="#FF000000" Margin="2,2,2,2" 
                                   StrokeThickness="0.5">
                            <Rectangle.Fill>
                                <LinearGradientBrush EndPoint="0.5,1" 
				StartPoint="0.5,0">
                                    <GradientStop Color="#FF828282" Offset="0"/>
                                    <GradientStop Color="#FF262626" Offset="1"/>
                                </LinearGradientBrush>
                            </Rectangle.Fill>
                        </Rectangle>
                    </Border>
                </Border>
            </Border>
        </Canvas>
        <Canvas Width="40" x:Name="cnvCloseButton" Cursor="Hand" Background="#00000000" 
                Opacity="1" Height="20" ToolTipService.ToolTip="Close">
            <Border Width="40" Height="20" 
		Background="#FF939393" BorderBrush="#FF000000" 
                    BorderThickness="1,1,1,1" CornerRadius="0,0,5,0">
                <Border BorderThickness="1,1,1,1" CornerRadius="0,0,5,0" Width="37" 
                        Height="16" x:Name="border">
                    <Border.Background>
                        <LinearGradientBrush EndPoint="0.514,0.623" 
                                             StartPoint="0.514,0.191">
                            <GradientStop Color="#FF956161" Offset="0"/>
                            <GradientStop Color="#FF490E0E" Offset="1"/>
                        </LinearGradientBrush>
                    </Border.Background>
                    <TextBlock Text="X" TextWrapping="Wrap" Foreground="#FFECECEC" 
                               HorizontalAlignment="Center" VerticalAlignment="Center" 
                               x:Name="textBlock"/>
                </Border>
            </Border>
        </Canvas>
    </StackPanel>
    <Rectangle Fill="#00FFFFFF" Margin="0,0,0,0" x:Name="rectTitleMask" 
               Grid.ColumnSpan="2"/>
</Grid>

由于它位于 Grid 中,因此可以根据视图进行缩放。按钮面板具有固定的视图,标题部分具有灵活的大小。如果您在设计视图中查看上面的 XAML,它将看起来像这样。

image

实现自定义边框窗口行为

现在打开 ControlBar.xaml 的代码隐藏文件,并向其中添加一个名为“Title”的 DependencyProperty,它将负责更改自定义窗口的标题。

public string Title
{
    get { return (string)GetValue(TitleProperty); }
    set { SetValue(TitleProperty, value); }
}

public static readonly DependencyProperty TitleProperty =
    DependencyProperty.Register("Title", typeof(string), 
	typeof(ControlBar), new PropertyMetadata(string.Empty));

现在,在 ControlBar 类的构造函数中,检查应用程序是否正在脱离浏览器运行并且是否具有足够的运行权限。如果是,则将控件的可见性设置为可见,并注册按钮事件以分别触发最小化、最大化和关闭事件。如果应用程序在浏览器中运行,则只需将控件的可见性设置为折叠,因此无需注册事件。

这是您的代码片段。

if (App.IsRunningOOBWithPermission)
{
    this.Visibility = Visibility.Visible;
    this.cnvMaximizeButton.MouseLeftButtonDown += cnvMaximizeButton_MouseLeftButtonDown;
    this.cnvMinimizeButton.MouseLeftButtonDown += cnvMinimizeButton_MouseLeftButtonDown;
    this.cnvCloseButton.MouseLeftButtonDown += cnvCloseButton_MouseLeftButtonDown;
    this.MouseLeftButtonDown += ControlBar_MouseLeftButtonDown;
}
else
{
    this.Visibility = Visibility.Collapsed;
}

请记住,“App.IsRunningOOBWithPermission”是实现于 App 类中的一个 static 属性,它表示以下内容的布尔输出:

((App.Current.IsRunningOutOfBrowser) && (App.Current.HasElevatedPermissions))

可能会有一个问题:在事件块中应该编写什么代码?别担心,您只需要尽可能简单地执行操作。

void ControlBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    App.Current.MainWindow.DragMove();
}

void cnvCloseButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    App.Current.MainWindow.Close();
}

void cnvMinimizeButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    App.Current.MainWindow.WindowState = WindowState.Minimized;
}

void cnvMaximizeButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    if (App.Current.MainWindow.WindowState == WindowState.Normal)
    {
        App.Current.MainWindow.WindowState = WindowState.Maximized;
    }
    else
    {
        App.Current.MainWindow.WindowState = WindowState.Normal;
    }
}

配置脱离浏览器设置

现在,将“ControlBarusercontrol 添加到您的页面中,然后运行您的 Silverlight 应用程序。您会发现 ControlBar 不在浏览器窗口中。这是因为只有在我们从浏览器窗口之外运行应用程序时它才会可用。

image

好的,那么我们可以继续将其安装到浏览器之外吗?是的,但为此我们需要做一些技巧。转到 Silverlight 项目的属性。在 Silverlight 窗格中,选择“启用脱离浏览器运行应用程序”,这将使“脱离浏览器设置…”按钮可用。单击它以进行更多设置。

image

在“设置”对话框窗口中,选择“显示安装菜单”,这将在 Silverlight 上下文菜单中创建一个菜单项。一旦您运行应用程序并右键单击该应用程序,您将看到一个“安装”菜单项。我稍后会回到这个部分。

现在,选中“在浏览器外运行时需要提升的信任”,如下所示,并将“窗口样式”选择为“无边框”。这将使默认边框窗口的可见性设置为折叠,并且如果您在 OOB 模式下运行,默认情况下您将看不到任何窗口边框。完成这些设置后,单击“确定”保存配置。您还可以更改“窗口标题”、“大小”以及那里提供的其他选项。

image

运行 OOB 应用程序

现在生成并运行您的应用程序,它将在浏览器窗口中加载,并且您不会在那里看到任何控件栏,因为我们编写了代码在浏览器中运行时将其折叠。右键单击 Silverlight 应用程序。这将显示 Silverlight 上下文菜单,其中包含“Silverlight”和“安装”两个菜单项。单击第二个菜单项将其作为 OOB 安装到您的本地驱动器。安装完成后,它将自动在脱离浏览器的窗口中运行该应用程序。现在您会看到它显示了我们的自定义窗口,而不是默认的窗口边框。正如我们所实现的,您可以使用我们的控件从标题栏拖动窗口、最小化、最大化甚至关闭窗口。

image

结束语

正如我之前提到的,这是一种在 Silverlight 4 中自定义 OOB 窗口的简单方法。现在您可以实现更多功能,如调整大小、边框粗细、动画和样式等,以满足您的业务需求。再次强调,最好将其实现为自定义控件而不是用户控件,这将为您提供对每个部分的更多控制。继续享受这个新功能吧。

您可以下载示例项目:自定义 Silverlight 4 OOB 窗口

历史

  • 2010 年 3 月 27 日:初始帖子
© . All rights reserved.