zoukankan      html  css  js  c++  java
  • MS CRM 2011 如何创建一个Silverlight 程序

    原创地址:http://www.cnblogs.com/jfzhu/archive/2013/03/05/2943711.html

    转载请注明出处

    我在以前的文章中介绍过如何安装Silverlight插件,参见MS CRM 2011 为64位Outlook安装Silverlight。今天我们来创建一个简单的Silverlight程序,该程序显示出CRM中所有的active contacts。

    1. 创建一个Silverlight Application

    image

    image

    2. 生成 WCF Data Services Client Data Service Classes

    CRM –> Settings –> Customizations –> Developer Resources .

    Download Organization Data Service 的 CSDL

    image

    保存CSDL文件

    3. 在Silverlight Application中添加 Service Reference

    image

    顺便提一下,如果在CRM customization中,某entity的name与该entity的某个field name相同,或者entity name 与某Relationship name相同的话,添加引用都会引起编译错误,所以在定制CRM的时候要注意,避免entity name与field name或者relationship name相同。

    4. 在Silverlight Application 项目中添加 Reference System.Xml.Linq

    5. 添加一个新类 DataServiceContextExtensions.cs

    注意修改你的namespace和类名escrmContext,namespace应与Reference.cs的namepsace相同,escrmContext也应与Reference.cs中的DataServiceContext相同。

    image

    using System; 
    using System.Linq; 
    using System.Data.Services.Client; 
    using System.Reflection; 
    using System.Collections.Generic; 
    using System.ComponentModel; 
    using System.Collections.ObjectModel; 
    using System.Xml.Linq;
    
    namespace SilverlightApplication3.CrmODataService 
    { 
        partial class escrmContext 
        { 
            #region Methods 
            partial void OnContextCreated() 
            { 
                this.ReadingEntity += this.OnReadingEntity; 
                this.WritingEntity += this.OnWritingEntity; 
            } 
            #endregion
    
            #region Event Handlers 
            private void OnReadingEntity(object sender, ReadingWritingEntityEventArgs e) 
            { 
                ODataEntity entity = e.Entity as ODataEntity; 
                if (null == entity) 
                { 
                    return; 
                }
    
                entity.ClearChangedProperties(); 
            }
    
            private void OnWritingEntity(object sender, ReadingWritingEntityEventArgs e) 
            { 
                ODataEntity entity = e.Entity as ODataEntity; 
                if (null == entity) 
                { 
                    return; 
                }
    
                entity.RemoveUnchangedProperties(e.Data); 
                entity.ClearChangedProperties(); 
            } 
            #endregion 
        }
    
        public abstract class ODataEntity 
        { 
            private readonly Collection<string> ChangedProperties = new Collection<string>();
    
            public ODataEntity() 
            { 
                EventInfo info = this.GetType().GetEvent("PropertyChanged"); 
                if (null != info) 
                { 
                    PropertyChangedEventHandler method = new PropertyChangedEventHandler(this.OnEntityPropertyChanged);
    
                    //Ensure that the method is not attached and reattach it 
                    info.RemoveEventHandler(this, method); 
                    info.AddEventHandler(this, method); 
                } 
            }
    
            #region Methods 
            public void ClearChangedProperties() 
            { 
                this.ChangedProperties.Clear(); 
            }
    
            internal void RemoveUnchangedProperties(XElement element) 
            { 
                const string AtomNamespace = "http://www.w3.org/2005/Atom";
                const string DataServicesNamespace = "http://schemas.microsoft.com/ado/2007/08/dataservices";
                const string DataServicesMetadataNamespace = DataServicesNamespace + "/metadata";
    
                if (null == element) 
                { 
                    throw new ArgumentNullException("element"); 
                }
    
                List<XElement> properties = (from c in element.Elements(XName.Get("content", AtomNamespace) 
                                                       ).Elements(XName.Get("properties", DataServicesMetadataNamespace)).Elements() 
                                             select c).ToList();
    
                foreach (XElement property in properties) 
                { 
                    if (!this.ChangedProperties.Contains(property.Name.LocalName)) 
                    { 
                        property.Remove(); 
                    } 
                } 
            }
    
            private void OnEntityPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
            { 
                if (!this.ChangedProperties.Contains(e.PropertyName)) 
                { 
                    this.ChangedProperties.Add(e.PropertyName); 
                } 
            } 
            #endregion 
        } 
    } 

    6. 将Reference.cs中的“: global::System.ComponentModel.INotifyPropertyChanged”替换为“: ODataEntity, global::System.ComponentModel.INotifyPropertyChanged

    7. 在Silverlight Application项目中添加Utilities Folder,并添加新类ServerUtility.cs

    using System; 
    using System.Windows.Browser;
    
    namespace SilverlightApplication3.Utilities 
    { 
        public static class ServerUtility 
        { 
            /// <summary> 
            /// Returns the ServerUrl from Microsoft Dynamics CRM 
            /// </summary> 
            /// <returns>String representing the ServerUrl or String.Empty if not found.</returns> 
            public static String GetServerUrl() 
            { 
                String serverUrl = String.Empty;
    
                //Try to get the ServerUrl from the Xrm.Page object 
                serverUrl = GetServerUrlFromContext();
    
                return serverUrl; 
            }
    
            /// <summary> 
            /// Attempts to retrieve the ServerUrl from the Xrm.Page object 
            /// </summary> 
            /// <returns></returns> 
            private static String GetServerUrlFromContext() 
            { 
                try 
                { 
                    // If the Silverlight is in a form, this will get the server url 
                    ScriptObject xrm = (ScriptObject)HtmlPage.Window.GetProperty("Xrm"); 
                    ScriptObject page = (ScriptObject)xrm.GetProperty("Page"); 
                    ScriptObject pageContext = (ScriptObject)page.GetProperty("context");
    
                    String serverUrl = (String)pageContext.Invoke("getServerUrl");
    
                    //The trailing forward slash character from CRM Online needs to be removed. 
                    if (serverUrl.EndsWith("/")) 
                    { 
                        serverUrl = serverUrl.Substring(0, serverUrl.Length - 1); 
                    }
    
                    return serverUrl; 
                } 
                catch 
                { 
                    return String.Empty; 
                } 
            } 
        } 
    } 

    8. 删除Silverlight Application Web项目中的.aspx文件

    9. 删除Silverlight Application Web项目中的Silverlight.js文件

    10. 打开Silverlight Application Web项目中的.html文件, 修改style silverlightControlHost

    #silverlightControlHost
    {
    height: 100%;
    100%;
    text-align: center;
    }

    删除对 Silverlight.js的引用    <script type="text/javascript" src="Silverlight.js"></script>

    添加引用<script src="ClientGlobalContext.js.aspx" type="text/javascript"></script>

    如果你上传到CRM中的web resource 的名为  new_/testpage.html,那么你的引用就为

    <script src="../ClientGlobalContext.js.aspx" type="text/javascript"></script>

    假如你要上传的html web resource为new_testpage.html,xap web resource 为 new_testsilverlight.xap,将object tag修改为

    <param name="source" value="new_testsilverlight.xap"/>

    11. 至此项目的创建工作就基本完成了

    image

    12. 下面来完成在DataGrid中显示所有的active contacts

    MainPage.xaml代码如下:

    <UserControl xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"  x:Class="SilverlightApplication3.MainPage" 
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:SilverlightApplication3" 
        mc:Ignorable="d" 
        d:DesignHeight="300" d:DesignWidth="400"> 
        
        <UserControl.Resources> 
            <local:YesNoValueConverter x:Key="myYesNoValueConverter"/> 
            <local:GenderCodeConverter x:Key="myGenderCodeConverter"/> 
        </UserControl.Resources>
    
        <Grid x:Name="LayoutRoot" Background="White"> 
            <StackPanel x:Name="MessagePanel" VerticalAlignment="Top" /> 
            <sdk:DataGrid x:Name="myDataGrid" AutoGenerateColumns="False" IsReadOnly="True" > 
                <sdk:DataGrid.Columns> 
                    <sdk:DataGridTextColumn x:Name="FirstNameColumn" Header="First Name" Binding="{Binding FirstName, Mode=OneTime}" /> 
                    <sdk:DataGridTextColumn x:Name="LastNameColumn" Header="Last Name" Binding="{Binding LastName, Mode=OneTime}" /> 
                    <sdk:DataGridTextColumn x:Name="DoNotEmailColumn" Header="Do Not Email" Binding="{Binding DoNotEMail, Mode=OneTime, Converter={StaticResource myYesNoValueConverter}}"  /> 
                    <sdk:DataGridTextColumn x:Name="ExchangeRateColumn" Header="Exchange Rate" Binding="{Binding ExchangeRate, Mode=OneTime, StringFormat=\{0:n2\}}"  /> 
                    <sdk:DataGridTextColumn x:Name="BirthDateColumn" Header="Birth Date" Binding="{Binding BirthDate, Mode=OneTime, StringFormat=\{0:MM/dd/yyyy\}}"  /> 
                    <sdk:DataGridTextColumn x:Name="GenderCodeColumn" Header="Gender" Binding="{Binding Path=GenderCode.Value, Mode=OneTime, Converter={StaticResource myGenderCodeConverter}}"  /> 
                    <sdk:DataGridTextColumn x:Name="ParentColumn" Header="Parent Customer" Binding="{Binding Path=ParentCustomerId.Name, Mode=OneTime}" /> 
                </sdk:DataGrid.Columns> 
            </sdk:DataGrid>        
        </Grid> 
    </UserControl>

    MainPage.xaml.cs代码如下:

    using System; 
    using System.Data.Services.Client; 
    using System.Linq; 
    using System.Threading; 
    using System.Windows.Controls; 
    using SilverlightApplication2.CrmODataService; 
    using SilverlightApplication2.Utilities; 
    using System.Windows.Data;
    
    namespace SilverlightApplication3 
    { 
        public partial class MainPage : UserControl 
        { 
            private SynchronizationContext _syncContext; 
            private escrmContext _context; 
            private String _serverUrl;
    
            public MainPage() 
            { 
                InitializeComponent();
    
                //Keeps a reference to the UI thread 
                _syncContext = SynchronizationContext.Current;
    
                //Get the ServerUrl (ServerUrl is formatted differently OnPremise than OnLine) 
                _serverUrl = ServerUtility.GetServerUrl();
    
                if (!String.IsNullOrEmpty(_serverUrl)) 
                {
    
                    //Setup Context 
                    _context = new escrmContext(new Uri(String.Format("{0}/xrmservices/2011/organizationdata.svc/", 
                            _serverUrl), UriKind.Absolute));
    
                    //This is important because if the entity has new 
                    //attributes added the code will fail. 
                    _context.IgnoreMissingProperties = true;
    
                    SearchContacts(); 
                } 
                else 
                { 
                    //No ServerUrl was found. Display message. 
                    MessagePanel.Children.Add(new TextBlock() 
                    { 
                        Text = 
                            "Unable to access server url. Launch this Silverlight " + 
                            "Web Resource from a CRM Form OR host it in a valid " + 
                            "HTML Web Resource with a " + 
                            "<script src='ClientGlobalContext.js.aspx' " + 
                            "type='text/javascript'></script>" 
                    }); 
                } 
            }
    
            private void SearchContacts() 
            { 
                DataServiceQuery<Contact> query = (DataServiceQuery<Contact>)_context.ContactSet.Where(x => x.StateCode.Value.Value == 0); 
                query.BeginExecute(OnContactSearchComplete, query); 
            }
    
            private void OnContactSearchComplete(IAsyncResult result) 
            { 
                try 
                { 
                    //Get the original query back from the result. 
                    DataServiceQuery<Contact> query = result.AsyncState as DataServiceQuery<Contact>;
    
                    this.myDataGrid.ItemsSource = new DataServiceCollection<Contact>(query.EndExecute(result));                 
                } 
                catch (SystemException se) 
                { 
                    _syncContext.Send(new SendOrPostCallback(showErrorDetails), se); 
                } 
            }
    
            private void showErrorDetails(object ex) 
            { 
                //Assure the control is visible 
                MessagePanel.Visibility = System.Windows.Visibility.Visible;
    
                Exception exception = (Exception)ex; 
                String type = exception.GetType().ToString();
    
                MessagePanel.Children.Add(new TextBlock() 
                { 
                    Text = 
                        String.Format("{0} Message: {1}", type, exception.Message) 
                });
    
                MessagePanel.Children.Add(new TextBlock() 
                { 
                    Text = 
                        String.Format("Stack: {0}", exception.StackTrace) 
                });
    
                if (exception.InnerException != null) 
                { 
                    String exceptType = exception.InnerException.GetType().ToString(); 
                    MessagePanel.Children.Add(new TextBlock() 
                    { 
                        Text = 
                            String.Format("InnerException: {0} : {1}", exceptType, 
                            exception.InnerException.Message) 
                    }); 
                } 
            } 
        }
    
        public class YesNoValueConverter : IValueConverter 
        { 
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
            { 
                bool isYes = bool.Parse(value.ToString()); 
                if (isYes) 
                    return "Yes"; 
                else 
                    return "No"; 
            } 
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
            { 
                string boolText = value.ToString().ToLower(); 
                if (boolText == "yes") 
                    return true; 
                else if (boolText == "no") 
                    return false; 
                else 
                    throw new InvalidOperationException("Please enter 'yes' or 'no'."); 
            } 
        }
    
        public class GenderCodeConverter : IValueConverter 
        { 
            public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
            { 
                if (value == null) 
                    return ""; 
                int gendercode = int.Parse(value.ToString()); 
                if (gendercode == 1) 
                    return "Male"; 
                else if (gendercode == 2) 
                    return "Female"; 
                else if (gendercode == 3) 
                    return "Unknown"; 
                else 
                    return "null";            
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
            { 
                return null; 
    
            } 
        } 
    }

    在上面的代码中,在DataGrid中分别显示了不同种类的field,包括Single Line Text, Two Options, decimal, OptionSet, DateTime,以及lookup。对 Two Options和OptionSet使用了Converter,当然其实对于获取GenderCode的Label应该去读取Metadata;对decimal和DateTime使用了StringFormat。

    最后看一下效果截图:

    image

    总结:本文演示了如何为CRM创建一个Silverlight程序,并且如何将contact 的不同种类的field bind到DataGrid中。

  • 相关阅读:
    CM金丝雀Canary报错
    ucloud自动创建instance
    拷贝文件
    10.使用du将文件按大小进行排序
    9.ssh登录慢
    8.perf top系统性能分析工具
    7.Linux查找目录下的所有文件中是否含有某个字符串
    6.Linux查看哪个进程占用磁盘IO
    5.Linux常用排查命令
    4.Linux系统命令及其使用详解
  • 原文地址:https://www.cnblogs.com/jfzhu/p/2943711.html
Copyright © 2011-2022 走看看