首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在WPF 4应用程序中承载Silverlight 4应用程序?

如何在WPF 4应用程序中承载Silverlight 4应用程序?
EN

Stack Overflow用户
提问于 2011-06-13 22:23:33
回答 3查看 2.4K关注 0票数 4

我有一个Silverlight4应用程序,我想把它作为一个Kiosk应用程序。它必须是全屏的,支持触摸的,最重要的是要有完全的信任。我正在考虑使用一个WPF应用程序来托管Silverlight XAP。我知道WPF/XNA SilverlightViewport,但是这个解决方案似乎不提供WPF和Silverlight之间的通信。

这真的会为我节省很多时间。我不必维护两个截然不同的应用程序来做完全相同的事情,也不必每次进行更改时都部署到数百个信息亭。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-04-14 06:09:26

我知道这是个老生常谈的问题,但我确实有一个解决方案。

我做的就是这个场景。我在WPF主机上托管了一个Silverlight应用程序。我使用自托管WCF来提供双工net tcp服务。要做到这一点,您还必须有一个HTTP托管的clientaccesspolicy.xml,我也从相同的服务中自行托管了它。

我希望我能有足够的解释来让事情开始。我会包括一些样本,我可以,但由于项目,我不能分享一切。

首先,一些考虑因素: 1) net tcp在Silverlight和WPF之间是不安全的,因为Silverlight (从版本4开始-只是测试版本5)不能进行安全连接,所以如果你要使用它,你必须使用自己的加密。

2)双工WCF有两种方法,一种是使用HTTP。HTTP方法“轮询”服务,以查看是否有来自主机的客户端命令。这就使得它比net tcp慢得多。另一种是使用net tcp (如前所述)。只有http方法支持开箱即用的加密。

3)当您在WPF主机中托管Silverlight应用程序时,当您开始调试时,您将无法调试您的Silverlight应用程序,因为调试器将不会连接到(正如它所看到的那样)外部Silverlight应用程序,只能连接到WPF。要解决此问题,您必须在启动WPF主机时“激活”Silverlight应用程序的附件。

现在来看代码:

远程服务接口:

代码语言:javascript
运行
复制
using System.ServiceModel;

namespace RemoteService
{
    [ServiceContract(CallbackContract = typeof(IRemoteCallbackService))]
    public interface IRemoteService
    {
        [OperationContract]
        void TestCallback();

        // TODO: Add your service operations here
    }

    [ServiceContract]
    public interface IRemoteCallbackService
    {
        [OperationContract(IsOneWay = true)]
        void OnTestCallbackComplete();

        // TODO: Add your service operations here
    }
}

您的策略监听程序接口:

代码语言:javascript
运行
复制
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace RemoteService
{
    [ServiceContract]
    public interface IPolicyRetriever
    {
        [OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
        Stream GetSilverlightPolicy();

        [OperationContract, WebGet(UriTemplate = "/crossdomain.xml")]
        Stream GetFlashPolicy();
    }
}

实际的服务实现:

代码语言:javascript
运行
复制
using System.Text;

namespace RemoteService
{
    public class RemoteService : IRemoteService, IPolicyRetriever
    {
        IRemoteCallbackService client = null;

        public void TestCallback()
        {
            client = OperationContext.Current.GetCallbackChannel<IRemoteCallbackService>();
            client.OnTestCallbackComplete();
        }

        #region Cross Domain Policy Implementation

        private Stream StringToStream(string result)
        {
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
            return new MemoryStream(Encoding.UTF8.GetBytes(result));
        }

        //<grant-to>
        //<resource path="/" include-subpaths="true"/>
        //<socket-resource port="4502-4534" protocol="tcp" />
        //</grant-to>

        Stream IPolicyRetriever.GetSilverlightPolicy()
        {
            string result = @"<?xml version=""1.0"" encoding=""utf-8""?><access-policy><cross-domain-access><policy><allow-from http-request-headers=""*""><domain uri=""*""/></allow-from><grant-to><resource path=""/"" include-subpaths=""true""/><socket-resource port=""4502-4534"" protocol=""tcp"" /></grant-to></policy></cross-domain-access></access-policy>";
            return StringToStream(result);
        }

        Stream IPolicyRetriever.GetFlashPolicy()
        {
            string result = @"<?xml version=""1.0""?><!DOCTYPE cross-domain-policy SYSTEM ""http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd""><cross-domain-policy><allow-access-from domain=""*"" /></cross-domain-policy>";
            return StringToStream(result);
        }

        #endregion Cross Domain Policy Implementation
    }
}

以上代码应该位于一个dll项目中的单独类中,然后由WPF宿主引用。

并将其托管在控制台应用程序中(您需要将其转换为WPF):

代码语言:javascript
运行
复制
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using LocalService;
using RemoteService;

namespace Host
{
    internal class Program
    {
        /// <summary>
        /// Main host entry point, this starts our listeners
        /// </summary>
        /// <param name="args">The args.</param>
        private static void Main(string[] args)
        {
            // Start our listeners
            StartListeners(80, 4504, true);
        }

        /// <summary>
        /// Starts the listeners.
        /// </summary>
        private static void StartListeners(int HttpPort = 80, int NetTcpPort = 4504, bool StartRemoteService = true)
        {
            Console.WriteLine("Starting Policy Listener");

            string policyaddress = "http://" + Environment.MachineName + ":" + HttpPort.ToString();
            string locallistener = "net.tcp://" + Environment.MachineName + ":" + NetTcpPort.ToString();

            // Start our policy listener and (if required) our remote http service:
            using (System.ServiceModel.ServiceHost policyandremoteservicehost = new System.ServiceModel.ServiceHost(typeof(RemoteService.RemoteService), new Uri(policyaddress)))
            {
                policyandremoteservicehost.AddServiceEndpoint(typeof(IPolicyRetriever), new System.ServiceModel.WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());

                // if we are to start our remote service here too, then add that endpoint in:
                if (StartRemoteService)
                {
                    policyandremoteservicehost.AddServiceEndpoint(typeof(IRemoteService), new System.ServiceModel.PollingDuplexHttpBinding(), "RemoteService");
                }

                ServiceMetadataBehavior psmb = new ServiceMetadataBehavior();
                psmb.HttpGetEnabled = true;
                psmb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                policyandremoteservicehost.Description.Behaviors.Add(psmb);
                policyandremoteservicehost.Open();


                Console.WriteLine("WCF Host Running...");
                Console.WriteLine("Press <enter> to shutdown");
                Console.ReadLine();
                Console.WriteLine("Closing connections, please wait");
                policyandremoteservicehost.Close();
                Console.WriteLine("Closed policy and remote services");
            }
        }
    }
}

这应该会给你一些工作的机会。startremoteservice可用于仅将其设置为策略文件侦听器,这将允许您连接到远程服务,而该远程服务不必托管策略文件。

请记住,Silverlight只能连接到4502-4534范围内的HTTP/HTTPS端口和TCP端口。所包含的clientaccesspolicy.xml是完全不受限制的。

我希望这对某些人有用:)。

如果你愿意,请随时问我问题,我会留意的。

需要注意的几点:您可以通过此解决方案为托管的xap提供服务,因此不需要IIS。你也可以在浏览器之外运行你的Silverlight xap,并且仍然使用这些服务。

调试答案如下:Debugging Silverlight hosted in WPF

票数 3
EN

Stack Overflow用户

发布于 2011-06-13 22:31:25

您最好的选择是采用三层体系结构方法,利用WCF/RIA服务并在服务器端处理所有业务逻辑。

通过保持客户端精简并主要关注视图和视图逻辑,交换不同的客户端应该和交换任何其他组件一样简单。

在这一点上,如果你在你的客户端使用Silverlight,那么你可以从web上运行它,或者作为一个独立的应用程序,这意味着你也会想要使用WPF的原因很少。

票数 0
EN

Stack Overflow用户

发布于 2011-10-22 01:42:57

我有完全相同的要求。我的解决方案使用WPF在web浏览器控件中托管Silverlight。它们之间的通信是使用WCF服务设置的,这些服务也由WPF托管在一个漂亮的独立包中。您可以为WPF组件设置ClickOnce以简化更新。我利用WPF在客户机上扩展Silverlight (不需要提升信任),方法是公开用于SL的WCF服务以供使用(例如,GetComputerName,...)。唯一的问题是您正在使用WCF RIA服务,该服务不能在IIS外部托管。希望能有所帮助

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6331727

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档