MS CRM 2011 Silverlightプログラムの作成方法
44563 ワード
オリジナル住所:http://www.cnblogs.com/jfzhu/archive/2013/03/05/2943711.html
転載は出典を明記してください
以前の記事でSilverlightプラグインのインストール方法について説明しましたが、MS CRM 2011は64ビットOutlookにSilverlightをインストールを参照してください.今日はCRMのすべてのactive contactsを示す簡単なSilverlightプログラムを作成します.
1.Silverlightアプリケーションの作成
2.WCF Data Services Client Data Service Classの生成
CRM –> Settings –> Customizations –> Developer Resources .
Download Organization Data ServiceのCSDL
CSDLファイルの保存
3.SilverlightアプリケーションにService Referenceを追加
ちなみに、CRM customizationで、あるentityのnameがそのentityのあるfield nameと同じ、またはentity nameがあるRelationship nameと同じであれば、参照を追加してもコンパイルエラーが発生するので、CRMをカスタマイズする際にentity nameがfield nameまたはrelationship nameと同じにならないように注意してください.
4.Silverlightアプリケーション項目にReference Systemを追加する.Xml.Linq
5.新しいクラスDataServiceContextExtensionsを追加する.cs
あなたのnamespaceとクラス名escrmContextを修正することに注意して、namespaceはReference.csのnamepsaceは同じで、escrmContextもReference.csのDataServiceContextは同じです.
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アプリケーションプロジェクトにUtilities Folderを追加し、新しいクラスのServer Utilityを追加します.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アプリケーションWebプロジェクトから削除する.aspxファイル
9.SilverlightアプリケーションWebプロジェクトのSilverlightを削除する.jsファイル
10.SilverlightアプリケーションWebプロジェクトを開く.htmlファイル、style silverlightControlHostの変更
#silverlightControlHost { height: 100%; width: 100%; text-align: center; }
削除jsの参照
参照を追加
CRMにアップロードしたweb resourceの名前がnew_/testpage.html、それではあなたの引用は
もしあなたがアップロードするhtml web resourceがnew_ならtestpage.html,xap web resourceはnew_testsilverlight.xap,object tagを
11.このプロジェクトの作成作業はほぼ完了しました
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;
}
}
}
上記のコードでは、Single Line Text、Two Options、decimal、OptionSet、DateTime、lookupなど、DataGridにそれぞれ異なる種類のfieldが表示されています.Two OptionsとOptionSetにConverterを使用していますが、もちろんGenderCodeを取得したLabelに対してMetadataを読み込むべきです.decimalとDateTimeにStringFormatを使用しました.
最後に効果のスクリーンショットを見てみましょう.
まとめ:CRMのSilverlightプログラムを作成し、contactの異なる種類のfield bindをDataGridにどのようにするかを示します.