OpenXML - Apply bookmarks to paragraph in word document - openxml

Below code works fine using OPENXML (asp.net) and print us elements in word document with HEADING2... how can we apply bookmark to specific paragraph..
What we r trying is extract sections between two HEADINGs...We are wondering how to apply bookmark and how can we use that extract text between two bookmarks...
const string fileName = #"D:\DocFiles\Scan.docx";
const string documentRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
const string stylesRelationshipType = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
const string wordmlNamespace = "http://schemas.openxmlformats.org/wordprocessingml/2006/main";
XNamespace w = wordmlNamespace;
XDocument xDoc = null;
XDocument styleDoc = null;
using (Package wdPackage = Package.Open(fileName, FileMode.Open, FileAccess.Read))
{
PackageRelationship docPackageRelationship =
wdPackage
.GetRelationshipsByType(documentRelationshipType)
.FirstOrDefault();
if (docPackageRelationship != null)
{
Uri documentUri =
PackUriHelper
.ResolvePartUri(
new Uri("/", UriKind.Relative),
docPackageRelationship.TargetUri);
PackagePart documentPart =
wdPackage.GetPart(documentUri);
// Load the document XML in the part into an XDocument instance.
xDoc = XDocument.Load(XmlReader.Create(documentPart.GetStream()));
// Find the styles part. There will only be one.
PackageRelationship styleRelation =
documentPart.GetRelationshipsByType(stylesRelationshipType)
.FirstOrDefault();
if (styleRelation != null)
{
Uri styleUri = PackUriHelper.ResolvePartUri(documentUri, styleRelation.TargetUri);
PackagePart stylePart = wdPackage.GetPart(styleUri);
// Load the style XML in the part into an XDocument instance.
styleDoc = XDocument.Load(XmlReader.Create(stylePart.GetStream()));
}
}
}
string defaultStyle =
(string)(
from style in styleDoc.Root.Elements(w + "style")
where (string)style.Attribute(w + "type") == "paragraph" &&
(string)style.Attribute(w + "default") == "1"
select style
).First().Attribute(w + "styleId");
// Find all paragraphs in the document.
var paragraphs =
from para in xDoc
.Root
.Element(w + "body")
.Descendants(w + "p")
let styleNode = para
.Elements(w + "pPr")
.Elements(w + "pStyle")
.FirstOrDefault()
select new
{
ParagraphNode = para,
StyleName = styleNode != null ?
(string)styleNode.Attribute(w + "val") :
defaultStyle
};
// Retrieve the text of each paragraph.
var paraWithText =
from para in paragraphs
select new
{
ParagraphNode = para.ParagraphNode,
StyleName = para.StyleName,
Text = ParagraphText(para.ParagraphNode)
};
foreach (var p in paraWithText)
{
if (p.StyleName=="Heading2")
{
Response.Write(p.StyleName + " -" + p.Text);
Response.Write("</br>");
}
}

Here's a sample Bookmark class that I created to demonstrate how you can deal with bookmarks. It finds pairs of w:bookmarkStart and w:bookmarkEnd elements and shows how you can get hold of the w:r elements between those two markers. Based on that, you can process the text, e.g., as shown in the GetValue() method.
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using OpenXmlPowerTools;
namespace CodeSnippets.OpenXml.Wordprocessing
{
/// <summary>
/// Represents a corresponding pair of w:bookmarkStart and w:bookmarkEnd elements.
/// </summary>
public class Bookmark
{
private Bookmark(XElement root, string bookmarkName)
{
Root = root;
BookmarkStart = new XElement(W.bookmarkStart,
new XAttribute(W.id, -1),
new XAttribute(W.name, bookmarkName));
BookmarkEnd = new XElement(W.bookmarkEnd,
new XAttribute(W.id, -1));
}
private Bookmark(XElement root, XElement bookmarkStart, XElement bookmarkEnd)
{
Root = root;
BookmarkStart = bookmarkStart;
BookmarkEnd = bookmarkEnd;
}
/// <summary>
/// The root element containing both <see cref="BookmarkStart"/> and
/// <see cref="BookmarkEnd"/>.
/// </summary>
public XElement Root { get; }
/// <summary>
/// The w:bookmarkStart element.
/// </summary>
public XElement BookmarkStart { get; }
/// <summary>
/// The w:bookmarkEnd element.
/// </summary>
public XElement BookmarkEnd { get; }
/// <summary>
/// Finds a pair of w:bookmarkStart and w:bookmarkEnd elements in the given
/// <paramref name="root"/> element, where the w:name attribute value of the
/// w:bookmarkStart element is equal to <paramref name="bookmarkName"/>.
/// </summary>
/// <param name="root">The root <see cref="XElement"/>.</param>
/// <param name="bookmarkName">The bookmark name.</param>
/// <returns>A new <see cref="Bookmark"/> instance representing the bookmark.</returns>
public static Bookmark Find(XElement root, string bookmarkName)
{
XElement bookmarkStart = root
.Descendants(W.bookmarkStart)
.FirstOrDefault(e => (string) e.Attribute(W.name) == bookmarkName);
string id = bookmarkStart?.Attribute(W.id)?.Value;
if (id == null) return new Bookmark(root, bookmarkName);
XElement bookmarkEnd = root
.Descendants(W.bookmarkEnd)
.FirstOrDefault(e => (string) e.Attribute(W.id) == id);
return bookmarkEnd != null
? new Bookmark(root, bookmarkStart, bookmarkEnd)
: new Bookmark(root, bookmarkName);
}
/// <summary>
/// Gets all w:r elements between the bookmark's w:bookmarkStart and
/// w:bookmarkEnd elements.
/// </summary>
/// <returns>A collection of w:r elements.</returns>
public IEnumerable<XElement> GetRuns()
{
return Root
.Descendants()
.SkipWhile(d => d != BookmarkStart)
.Skip(1)
.TakeWhile(d => d != BookmarkEnd)
.Where(d => d.Name == W.r);
}
/// <summary>
/// Gets the concatenated inner text of all runs between the bookmark's
/// w:bookmarkStart and w:bookmarkEnd elements, ignoring paragraph marks
/// and page breaks.
/// </summary>
/// <remarks>
/// The output of this method can be compared to the output of the
/// <see cref="XElement.Value"/> property.
/// </remarks>
/// <returns>The concatenated inner text.</returns>
public string GetValue()
{
return GetRuns().Select(UnicodeMapper.RunToString).StringConcatenate();
}
}
}
The above class processes documents like the following (very simple test document):
<?xml version="1.0" encoding="utf-8"?>
<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
<w:body>
<w:p>
<w:r>
<w:t>First</w:t>
</w:r>
</w:p>
<w:bookmarkStart w:id="1" w:name="_Bm001" />
<w:p>
<w:r>
<w:t>Second</w:t>
</w:r>
</w:p>
<w:p>
<w:r>
<w:t>Third</w:t>
</w:r>
</w:p>
<w:bookmarkEnd w:id="1" />
<w:p>
<w:r>
<w:t>Fourth</w:t>
</w:r>
</w:p>
</w:body>
</w:document>
The above document is created by the following unit tests, which demonstrate how you could use the Bookmark class:
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using CodeSnippets.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using OpenXmlPowerTools;
using Xunit;
namespace CodeSnippets.Tests.OpenXml.Wordprocessing
{
public class BookmarkTests
{
/// <summary>
/// The w:name value of our bookmark.
/// </summary>
private const string BookmarkName = "_Bm001";
/// <summary>
/// The w:id value of our bookmark.
/// </summary>
private const int BookmarkId = 1;
/// <summary>
/// The test w:document with our bookmark, which encloses the two runs
/// with inner texts "Second" and "Third".
/// </summary>
private static readonly XElement Document =
new XElement(W.document,
new XAttribute(XNamespace.Xmlns + "w", W.w.NamespaceName),
new XElement(W.body,
new XElement(W.p,
new XElement(W.r,
new XElement(W.t, "First"))),
new XElement(W.bookmarkStart,
new XAttribute(W.id, BookmarkId),
new XAttribute(W.name, BookmarkName)),
new XElement(W.p,
new XElement(W.r,
new XElement(W.t, "Second"))),
new XElement(W.p,
new XElement(W.r,
new XElement(W.t, "Third"))),
new XElement(W.bookmarkEnd,
new XAttribute(W.id, BookmarkId)),
new XElement(W.p,
new XElement(W.r,
new XElement(W.t, "Fourth")))
)
);
/// <summary>
/// Creates a <see cref="WordprocessingDocument"/> for on a <see cref="MemoryStream"/>
/// testing purposes, using the given <paramref name="document"/> as the w:document
/// root element of the main document part.
/// </summary>
/// <param name="document">The w:document root element.</param>
/// <returns>The <see cref="MemoryStream"/> containing the <see cref="WordprocessingDocument"/>.</returns>
private static MemoryStream CreateWordprocessingDocument(XElement document)
{
var stream = new MemoryStream();
const WordprocessingDocumentType type = WordprocessingDocumentType.Document;
using (WordprocessingDocument wordDocument = WordprocessingDocument.Create(stream, type))
{
MainDocumentPart part = wordDocument.AddMainDocumentPart();
part.PutXDocument(new XDocument(document));
}
return stream;
}
[Fact]
public void GetRuns_WordprocessingDocumentWithBookmarks_CorrectRunsReturned()
{
// Arrange.
// Create a new Word document on a Stream, using the test w:document
// as the main document part.
Stream stream = CreateWordprocessingDocument(Document);
// Open the WordprocessingDocument on the Stream, using the Open XML SDK.
using WordprocessingDocument wordDocument = WordprocessingDocument.Open(stream, true);
// Get the w:document element from the main document part and find
// our bookmark.
XElement document = wordDocument.MainDocumentPart.GetXElement();
Bookmark bookmark = Bookmark.Find(document, BookmarkName);
// Act, getting the bookmarked runs.
IEnumerable<XElement> runs = bookmark.GetRuns();
// Assert.
Assert.Equal(new[] {"Second", "Third"}, runs.Select(run => run.Value));
}
[Fact]
public void GetText_WordprocessingDocumentWithBookmarks_CorrectRunsReturned()
{
// Arrange.
// Create a new Word document on a Stream, using the test w:document
// as the main document part.
Stream stream = CreateWordprocessingDocument(Document);
// Open the WordprocessingDocument on the Stream, using the Open XML SDK.
using WordprocessingDocument wordDocument = WordprocessingDocument.Open(stream, true);
// Get the w:document element from the main document part and find
// our bookmark.
XElement document = wordDocument.MainDocumentPart.GetXElement();
Bookmark bookmark = Bookmark.Find(document, BookmarkName);
// Act, getting the concatenated text contents of the bookmarked runs.
string text = bookmark.GetValue();
// Assert.
Assert.Equal("SecondThird", text);
}
}
}
You can find the full code example in my CodeSnippets GitHub repository. Look for the Bookmark and BookmarkTests classes and note that I'm using the Open-Xml-PowerTools.
You can obviously do more complicated things with those Open XML elements. This is just a simple example.

Related

Microsoft Azure Spatial anchors script problem

I haven't find so far any good and update script for manage the Microsoft Spatial Azure Anchors, could you please review this code and tell me more or less if i am in the right way or not ? Actually I am trying to minimize the code for having the pure functionality, but i am stack and i can't even find an understandable guideline
hope the code is readable and well documented.
thanks in advance.
Andrea
using Microsoft.Azure;
using Microsoft.Azure.SpatialAnchors;
using Microsoft.Azure.SpatialAnchors.Unity;
using Microsoft.MixedReality.OpenXR;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.XR.WSA;
using UnityEngine.XR.WSA.Input;
public class AnchorsManager : MonoBehaviour
{
/// <summary>
/// Input
/// </summary>
private GameObject localAnchor;
/// <summary>
/// AZURE settings AccountId
/// </summary>
private string AccountId = "00886172-b41a-....";
/// <summary>
/// AZURE settings AccountKey
/// </summary>
private string AccountKey = "09c3eddc-....";
/// <summary>
/// AZURE settings AccountDomain
/// </summary>
private string AccountDomain = "northeurope.mixedreality.azure.com";
/// <summary>
/// Azure session
/// </summary>
private CloudSpatialAnchorSession cloudSession;
/// <summary>
/// For Storing the object Ids
/// </summary>
private AnchorLocateCriteria criteria = new AnchorLocateCriteria();
protected List<string> anchorIdsToLocate = new List<string>();
void Start()
{
InitializeSession();
}
/// <summary>
/// Only when the user drag an object we can save the anchor with the latest position
/// </summary>
void onMouseObjectDown(GameObject prefab)
{
this.localAnchor = prefab;
this.cloudSession.Start();
}
/// <summary>
/// Inizialize the cloudSpatialAnchorSession.
/// </summary>
void InitializeSession()
{
try {
this.cloudSession = new CloudSpatialAnchorSession();
this.cloudSession.Configuration.AccountId = this.AccountId;
this.cloudSession.Configuration.AccountKey = this.AccountKey;
this.cloudSession.Configuration.AccountDomain = this.AccountDomain;
this.cloudSession.SessionUpdated += (sender, args) =>
{
if (args.Status.RecommendedForCreateProgress != 0)
{
this.CreateAnchor();
}
};
//WATCHERS
this.cloudSession.CreateWatcher(criteria);
this.cloudSession.AnchorLocated += (object sender, AnchorLocatedEventArgs args) =>
{
switch (args.Status)
{
case LocateAnchorStatus.Located:
CloudSpatialAnchor foundAnchor = args.Anchor;
Debug.Log("ASA Info: Anchor located! Identifier: " + args.Identifier);
break;
case LocateAnchorStatus.AlreadyTracked:
Debug.Log("This anchor has already been reported and is being tracked" + args.Identifier);
break;
case LocateAnchorStatus.NotLocated:
Debug.Log("ASA Info: Anchor not located. Identifier: " + args.Identifier);
break;
case LocateAnchorStatus.NotLocatedAnchorDoesNotExist:
Debug.LogError("ASA Error: Anchor not located does not exist. Identifier: " + args.Identifier);
break;
}
};
}
catch (Exception ex) {
Debug.LogError("Error on initialize the session: " + ex.Message);
}
}
/// <summary>
/// CreateAnchor
/// </summary>
async void CreateAnchor()
{
// Create Anchor in local;
localAnchor.AddComponent<CloudNativeAnchor>();
CloudNativeAnchor cloudNativeAnchor = localAnchor.GetComponent<CloudNativeAnchor>();
if (cloudNativeAnchor.CloudAnchor == null) { await cloudNativeAnchor.NativeToCloud(); }
// Add Anchor property;
CloudSpatialAnchor cloudAnchor = cloudNativeAnchor.CloudAnchor;
cloudAnchor.AppProperties[#"room"] = #"bagno";
cloudAnchor.AppProperties[#"product"] = #"saponetta";
cloudAnchor.Expiration = DateTimeOffset.Now.AddDays(7);
// Create Anchor
await cloudSession.CreateAnchorAsync(cloudAnchor);
Debug.Log("Cloud anchor created with ID = " + cloudAnchor.Identifier);
// Save Anchor ID
this.anchorIdsToLocate.Add(cloudAnchor.Identifier);
this.criteria.Identifiers = anchorIdsToLocate.ToArray();
Debug.Log("Anchor Id has been saved on the array");
}
}

error CS0117: 'EditorUtility' does not contain a definition for 'RequestScriptReload'

In unity I keep on getting this error that keeps on bugging me, I tried to remove packages to leave one of these errors and it kept on going on and on, i am developing a game right now using unity engine and the errors are a big pain for me, this is the code that someone asked for, i dont really have much else to write other than this, stackoverlow isnt letting me just post it because its too short
using System;
using System.IO;
using UnityEngine;
namespace UnityEditor.SettingsManagement
{
/// <inheritdoc />
/// <summary>
/// A settings repository that stores data local to a Unity project.
/// </summary>
[Serializable]
public sealed class PackageSettingsRepository : ISettingsRepository
{
const string k_PackageSettingsDirectory = "ProjectSettings/Packages";
const bool k_PrettyPrintJson = true;
bool m_Initialized;
[SerializeField]
string m_Name;
[SerializeField]
string m_Path;
[SerializeField]
SettingsDictionary m_Dictionary = new SettingsDictionary();
/// <summary>
/// Constructor sets the serialized data path.
/// </summary>
/// <param name="package">
/// The package name.
/// </param>
/// <param name="name">
/// A name for this settings file. Settings are saved in `ProjectSettings/Packages/{package}/{name}.json`.
/// </param>
public PackageSettingsRepository(string package, string name)
{
m_Name = name;
m_Path = GetSettingsPath(package, name);
m_Initialized = false;
AssemblyReloadEvents.beforeAssemblyReload += Save;
EditorApplication.quitting += Save;
}
void Init()
{
if (m_Initialized)
return;
m_Initialized = true;
if (File.Exists(path))
{
m_Dictionary = null;
var json = File.ReadAllText(path);
EditorJsonUtility.FromJsonOverwrite(json, this);
if(m_Dictionary == null)
m_Dictionary = new SettingsDictionary();
}
}
/// <value>
/// This repository implementation is relevant to the Project scope.
/// </value>
/// <inheritdoc cref="ISettingsRepository.scope"/>
public SettingsScope scope
{
get { return SettingsScope.Project; }
}
/// <value>
/// The full path to the settings file.
/// This corresponds to `Unity Project/Project Settings/Packages/com.unity.package/name`.
/// </value>
/// <inheritdoc cref="ISettingsRepository.path"/>
public string path
{
get { return m_Path; }
}
/// <summary>
/// The name of this settings file.
/// </summary>
public string name
{
get { return m_Name; }
}
// Cannot call FindFromAssembly from a constructor or field initializer
// static string CreateSettingsPath(Assembly assembly, string name)
// {
// var info = PackageManager.PackageInfo.FindForAssembly(assembly);
// return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, info.name, name);
// }
/// <summary>
/// Get a path for a settings file relative to the calling assembly package directory.
/// </summary>
/// <param name="packageName">The name of the package requesting this setting.</param>
/// <param name="name">An optional name for the settings file. Default is "Settings."</param>
/// <returns>A package-scoped path to the settings file within Project Settings.</returns>
public static string GetSettingsPath(string packageName, string name = "Settings")
{
return string.Format("{0}/{1}/{2}.json", k_PackageSettingsDirectory, packageName, name);
}
/// <summary>
/// Save all settings to their serialized state.
/// </summary>
/// <inheritdoc cref="ISettingsRepository.Save"/>
public void Save()
{
Init();
if (!File.Exists(path))
{
var directory = Path.GetDirectoryName(path);
Directory.CreateDirectory(directory);
}
#if UNITY_2019_3_OR_NEWER
if (!AssetDatabase.IsOpenForEdit(path))
{
if (!AssetDatabase.MakeEditable(path))
{
Debug.LogWarning($"Could not save package settings to {path}");
return;
}
}
#endif
try
{
File.WriteAllText(path, EditorJsonUtility.ToJson(this, k_PrettyPrintJson));
}
catch (UnauthorizedAccessException)
{
Debug.LogWarning($"Could not save package settings to {path}");
}
}
/// <summary>
/// Set a value for key of type T.
/// </summary>
/// <param name="key">The settings key.</param>
/// <param name="value">The value to set. Must be serializable.</param>
/// <typeparam name="T">Type of value.</typeparam>
/// <inheritdoc cref="ISettingsRepository.Set{T}"/>
public void Set<T>(string key, T value)
{
Init();
m_Dictionary.Set<T>(key, value);
}
/// <summary>
/// Get a value with key of type T, or return the fallback value if no matching key is found.
/// </summary>
/// <param name="key">The settings key.</param>
/// <param name="fallback">If no key with a value of type T is found, this value is returned.</param>
/// <typeparam name="T">Type of value to search for.</typeparam>
/// <inheritdoc cref="ISettingsRepository.Get{T}"/>
public T Get<T>(string key, T fallback = default(T))
{
Init();
return m_Dictionary.Get<T>(key, fallback);
}
/// <summary>
/// Does the repository contain a setting with key and type.
/// </summary>
/// <param name="key">The settings key.</param>
/// <typeparam name="T">The type of value to search for.</typeparam>
/// <returns>True if a setting matching both key and type is found, false if no entry is found.</returns>
/// <inheritdoc cref="ISettingsRepository.ContainsKey{T}"/>
public bool ContainsKey<T>(string key)
{
Init();
return m_Dictionary.ContainsKey<T>(key);
}
/// <summary>
/// Remove a key value pair from the settings repository.
/// </summary>
/// <param name="key"></param>
/// <typeparam name="T"></typeparam>
/// <inheritdoc cref="ISettingsRepository.Remove{T}"/>
public void Remove<T>(string key)
{
Init();
m_Dictionary.Remove<T>(key);
By the definition of 'RequestScriptReload' :
"The Unity Editor reloads script assemblies asynchronously on the next frame. This resets the state of all the scripts, but Unity does not compile any code that has changed since the previous compilation."
That means that your problem is probably with something that you changed.
You can try:
Going back to the last time everything wored and go on from there.
Closing all of you unity and scripting applications and opening it again.

Entity Framework 5- Dynamically generating Enum from Values stored in Database

So, I have an existing lookup table in my database that stores an ID column(int), a description/Name for the ID Value. We have been using the data in this table for enumeration purposes.
We have since moved to using Entity Framework 5 and CodeFirst, but our lookup values are still in the database. What we would like to do is create an entity to represent the values, preferably an enum to access the values and names in that table and make them available for use in our application.
Normally, the code below would make sense for dynamically building an enumeration type from database values, but we want to get away from doing this.
static void GenerateStateEnumerations(String enumassemblyName, String enumTypeName, String assemblyName, IDictionary<int, String> EnumDB)
{
// Get the current application domain for the current thread.
AppDomain currentDomain = AppDomain.CurrentDomain;
// Create a dynamic assembly in the current application domain,
// and allow it to be executed and saved to disk.
AssemblyName EnumassemblyName = new AssemblyName(enumassemblyName);
AssemblyBuilder ab = currentDomain.DefineDynamicAssembly(
EnumassemblyName, AssemblyBuilderAccess.RunAndSave);
// Define a dynamic module in assemblyName assembly. For a single-
// module assembly, the module has the same name as the assembly.
ModuleBuilder mb = ab.DefineDynamicModule(EnumassemblyName.Name, EnumassemblyName.Name + ".dll");
// Define a public enumeration with the name "Elevation" and an
// underlying type of Integer.
EnumBuilder eb = mb.DefineEnum(enumTypeName, TypeAttributes.Public, typeof(int));
// Define the enumeration members
foreach (KeyValuePair<int, String> element in EnumDB)
{
eb.DefineLiteral(element.Value, element.Key);
}
// Create the type and save the assembly.
Type finished = eb.CreateType();
//Save the assembly via the assembly builder
ab.Save(EnumassemblyName.Name + ".dll");
}
How do I, in EF 5, create an entity that is an enumeration entity to represent the data stored in this table? Is this currently possible?
I know you said that you didn't want to do this dynamically, but have you looked at using text templates? If you use a text template (*.tt T4 file) The enum will be dynamically generated every time you do a build. Any new values in the table will be automatically added to the enum in the code.
Here's 1 example of how to create an enum from a text template:
<## template language="C#" hostSpecific="true" #>
<## output extension=".generated.cs" #>
<## Assembly Name="C:\Program Files (x86)\Common Files\microsoft shared\MSEnv\PublicAssemblies\EnvDTE.dll" #>
<## Assembly Name="System.Data" #>
<## assembly name="System.Configuration.dll" #>
<## Assembly Name="System.Core.dll" #>
<## import namespace="EnvDTE" #>
<## import namespace="System" #>
<## import namespace="System.Configuration" #>
<## import namespace="System.Data" #>
<## import namespace="System.Data.SqlClient" #>
<## import namespace="System.IO" #>
<## import namespace="System.Text.RegularExpressions" #>
<#
// This file dynamically creates Enumerations to be used in the [your project name] project.
// get an appSetting value
//string myAppSetting = AppSettings["myAppSetting"].Value;
// use a helper method to get value or default
// string absentAppSetting = (string)AppSettingValueOrDefault("xxx","default value for absent setting");
// get a project property
//string rootNamespace = Project.Properties.Item("RootNamespace").Value.ToString();
ConnectionStringSettings cs = ConnectionStrings["MyDBName"];
string tableName = "dbo.MyEnumTable"; // Path.GetFileNameWithoutExtension(Host.TemplateFile);
string path = Path.GetDirectoryName(Host.TemplateFile);
string columnId = "MyEnumTableId";
string columnName = "MyEnumTableValue";
string connectionString = cs.ConnectionString;
// Get containing project
IServiceProvider serviceProvider = (IServiceProvider)Host;
DTE dte = (DTE)serviceProvider.GetService(typeof(DTE));
Project project = dte.Solution.FindProjectItem(Host.TemplateFile).ContainingProject;
# > //remove space between # > issue with SO formatting
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
namespace <#= project.Properties.Item("DefaultNamespace").Value #>
{
/// <summary>
/// Auto generated enumeration from database table <#= tableName #>
/// </summary>
[GeneratedCode("TextTemplatingFileGenerator", "10")]
public enum MyEnumTableEnum
{
<#
SqlConnection conn = new SqlConnection(connectionString);
string command = string.Empty;
command = string.Format("select tbl.{0}, tbl.{1} from {2} as tbl order by tbl.{0}", columnId, columnName, tableName);
SqlCommand comm = new SqlCommand(command, conn);
conn.Open();
SqlDataReader reader = comm.ExecuteReader();
bool loop = reader.Read();
while(loop)
{
# > //remove space between # > issue with SO formatting
/// <summary>
/// <#= reader[columnName] #> configuration setting.
/// </summary>
<#= Pascalize(reader[columnName]) #> = <#= reader[columnId] #><# loop = reader.Read(); #><#= loop ? ",\r\n" : string.Empty #>
<#
}
#>
}
/// <summary>
/// This auto generated class is used to get or set the MyEnumTableEnum user friendly display names.
/// The 'values' object is of type Dictionary<int, string>
/// Usage: string keyValue = MyEnumTableDict.values[int key];
/// </summary>
public class MyEnumTableDict
{
public static Dictionary<int, string> values = new Dictionary<int, string>();
static MyEnumTableDict()
{
<#
reader.Close();
reader = comm.ExecuteReader();
loop = reader.Read();
while(loop)
{
#>
values[<#= reader[columnId] #>] = "<#= reader[columnName] #>";<#= "\r\n" #><# loop = reader.Read(); #>
<#
}
reader.Close();
reader.Dispose();
#>
}
}
}
<#+
/// <summary>
/// Used to Pascal-case objects
/// </summary>
private string Pascalize(object value)
{
Regex rx = new Regex(#"(?:[^a-zA-Z0-9]*)(?<first>[a-zA-Z0-9])(?<reminder>[a-zA-Z0-9]*)(?:[^a-zA-Z0-9]*)");
return rx.Replace(value.ToString(), m => m.Groups["first"].ToString().ToUpper() + m.Groups["reminder"].ToString().ToLower());
}
// Configuration Accessor Helpers
private static System.Configuration.Configuration _config;
private static EnvDTE.Project _project;
/// <summary>
/// Example:
/// <code>
/// string cs = ConnectionStrings["myConnectionString"].ConnectionString;
/// </code>
/// </summary>
private ConnectionStringSettingsCollection ConnectionStrings
{
get { return Configuration.ConnectionStrings.ConnectionStrings;}
}
/// <summary>
/// Example:
/// <code>
/// string setting = AppSettings["mySetting"].Value;
/// </code>
/// </summary>
private KeyValueConfigurationCollection AppSettings
{
get { return Configuration.AppSettings.Settings; }
}
/// <summary>
/// Returns value of setting, if present, otherwise defaultValue
/// </summary>
/// <param name="key">appSettings key</param>
/// <param name="defaultValue">value to return if setting is absent</param>
/// <returns></returns>
private object AppSettingValueOrDefault(string key,object defaultValue)
{
if (AppSettings[key] != null)
{
return AppSettings[key].Value;
}
return defaultValue;
}
/// <summary>
/// The app/web config file for hosting project, if any
/// </summary>
private System.Configuration.Configuration Configuration
{
get
{
if(_config==null)
{
string configurationFilename=null;
// examine each project item's filename looking for app.config or web.config
foreach (EnvDTE.ProjectItem item in Project.ProjectItems)
{
if (Regex.IsMatch(item.Name,"(app|web).config",RegexOptions.IgnoreCase))
{
// TODO: try this with linked files. is the filename pointing to the source?
configurationFilename=item.get_FileNames(0);
break;
}
}
if(!string.IsNullOrEmpty(configurationFilename))
{
// found it, map it and return it
ExeConfigurationFileMap configFile = null;
configFile = new ExeConfigurationFileMap();
configFile.ExeConfigFilename=configurationFilename;
_config = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(configFile, ConfigurationUserLevel.None);
}
}
return _config;
}
}
/// <summary>
/// The hosting project.
/// </summary>
private EnvDTE.Project Project
{
get
{
if(_project==null)
{
// Get the instance of Visual Studio that is hosting the calling file
EnvDTE.DTE env = (EnvDTE.DTE)((IServiceProvider)this.Host).GetService(typeof(EnvDTE.DTE));
// Gets an array of currently selected projects. Since you are either in this file saving it or
// right-clicking the item in solution explorer to invoke the context menu it stands to reason
// that there is 1 ActiveSolutionProject and that it is the parent of this file....
_project = (EnvDTE.Project)((Array)env.ActiveSolutionProjects).GetValue(0);
}
return _project;
}
}
#>
Update:
Forgot to include output class. Including now for completeness :)
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
namespace MyNameSpace
{
/// <summary>
/// Auto generated enumeration from database table dbo.MyEnumTable
/// </summary>
[GeneratedCode("TextTemplatingFileGenerator", "10")]
public enum MyEnumTableDictEnum
{
/// <summary>
/// description 1
/// </summary>
enumName1 = 1,
/// <summary>
/// description 2
/// </summary>
enumName2 = 2,
//..etc.
}
/// <summary>
/// This auto generated class is used to get or set the MyEnumTableDictEnum
/// user friendly display names.
/// The 'values' object is of type Dictionary<int, string>
/// Usage: string keyValue = MyEnumTableDict.values[int key];
/// </summary>
public class MyEnumTableDict
{
public static Dictionary<int, string> values = new Dictionary<int, string>();
static MyEnumTableDict()
{
values[1] = "EnumName1";
values[2] = "EnumName2";
values[3] = "...etc.";
}
}
}

Confusion with DropDownListFor<>

So what I am trying to do is import data from a database into a MVC2 DropDownListFor.
What I essentially have going is a roleplaying guild site I am working on for a friend. What the page should be doing is allowing a person to edit their character. So what is being passed into the page is the model containing the characters information. Then I have the view making a call to a method in the YourCharacterEdit model to get the information on a player character's race.
So I have tried to follow lots of different ideas that I have found from various tutorials online but nothing seems to be working. I am pretty much open to whatever ideas anyone might have at this point as to how I call fill up the drop down list. Currently I don't have much of a model to show because I keep scraping whatever I come up with.
The Controller:
if (Request.IsAuthenticated)
{
UserRepository _urepos = new UserRepository();
CharacterRepository _crepos = new CharacterRepository();
var check = _urepos.GetSpecificUserByName(User.Identity.Name);
var yourchar = _crepos.GetSpecificCharacter(CharID);
if (yourchar.CharUserRef == check.UserID)
{
//
YourCharacterEdit VarToReturn = new YourCharacterEdit();
VarToReturn.EmployeeID = yourchar.EmployeeID;
VarToReturn.CharFirstName = yourchar.CharFirstName;
VarToReturn.CharLastName = yourchar.CharLastName;
VarToReturn.CharGender = yourchar.CharGender;
VarToReturn.CharSpecies = yourchar.CharSpecies;
VarToReturn.CharDescription = yourchar.CharDescription;
VarToReturn.CharBackground = yourchar.CharBackground;
VarToReturn.CharJob = yourchar.CharJob;
return View("CharEdit", VarToReturn);
}
else
{
return View("401");
}
}
The View:
<div class="editor-field">
<%: Html.DropDownListFor(model => model.CharSpecies, ?)%>
<%: Html.ValidationMessageFor(model => model.CharSpecies) %>
</div>
So anyone have any good methods for getting the ListBox propagated?
Also the DB is access through guildEntities. The table is TBLCharS. The fields needed inside that table are CharS_id and CharS_name.
The first thing to do is define your model. The view should not need any additional data other than what you pass it in the model. Build your model and fill it up before calling the view.
My implementation is a bit overkill but here it goes:
In the model, create a container to hold the dropdown data:
public IEnumerable<SelectListItem> LocationList { get; set; }
In the controller, populate your model including the dropdown list:
model.LocationList = repository.GetLocationsSelectList(selectedLocationId);
I use a repository and Linq to grab the data from the database:
var q = (from l in Repository.For<LocationEntity>()
select new
{
RowId = l.RowId,
LocationString = l.Name,
});
var result = q.ToSelectList(a => a.RowId.ToString(), a => a.LocationString, a => a.RowId == locationId);
return result;
The ToSelectList extension I grabbed from somewhere (I forgot where):
public static class EnumerableExtensions
{
/// <summary>
/// Converts the source sequence into an IEnumerable of SelectListItem
/// </summary>
/// <param name="items">Source sequence</param>
/// <param name="nameSelector">Lambda that specifies the name for the SelectList items</param>
/// <param name="valueSelector">Lambda that specifies the value for the SelectList items</param>
/// <returns>IEnumerable of SelectListItem</returns>
public static IEnumerable<SelectListItem> ToSelectList<TItem, TValue>(this IEnumerable<TItem> items, Func<TItem, TValue> valueSelector, Func<TItem, string> nameSelector)
{
return items.ToSelectList(valueSelector, nameSelector, x => false);
}
/// <summary>
/// Converts the source sequence into an IEnumerable of SelectListItem
/// </summary>
/// <param name="items">Source sequence</param>
/// <param name="nameSelector">Lambda that specifies the name for the SelectList items</param>
/// <param name="valueSelector">Lambda that specifies the value for the SelectList items</param>
/// <param name="selectedItems">Those items that should be selected</param>
/// <returns>IEnumerable of SelectListItem</returns>
public static IEnumerable<SelectListItem> ToSelectList<TItem, TValue>(this IEnumerable<TItem> items, Func<TItem, TValue> valueSelector, Func<TItem, string> nameSelector, IEnumerable<TValue> selectedItems)
{
return items.ToSelectList(valueSelector, nameSelector, x => selectedItems != null && selectedItems.Contains(valueSelector(x)));
}
/// <summary>
/// Converts the source sequence into an IEnumerable of SelectListItem
/// </summary>
/// <param name="items">Source sequence</param>
/// <param name="nameSelector">Lambda that specifies the name for the SelectList items</param>
/// <param name="valueSelector">Lambda that specifies the value for the SelectList items</param>
/// <param name="selectedValueSelector">Lambda that specifies whether the item should be selected</param>
/// <returns>IEnumerable of SelectListItem</returns>
public static IEnumerable<SelectListItem> ToSelectList<TItem, TValue>(this IEnumerable<TItem> items, Func<TItem, TValue> valueSelector, Func<TItem, string> nameSelector, Func<TItem, bool> selectedValueSelector)
{
foreach (var item in items)
{
var value = valueSelector(item);
yield return new SelectListItem
{
Text = nameSelector(item),
Value = value.ToString(),
Selected = selectedValueSelector(item)
};
}
}
}
And finally, in your view:
<%: Html.LabelFor(m => m.LocationId)%>
<%: Html.DropDownListFor(m => m.LocationId, Model.LocationList, "<-- Select One -->")%>
<%: Html.ValidationMessageFor(m => m.LocationId)%>
Add a comment if you have any questions or need more code.

Menu service in Prism application CAL

I am trying to create a Prism (CAL) framework (this is my first forray into CAL) and am having difficulty devising a service for registering menu items for a region). Here is what I have come up with so far...
/// <summary>
/// Menu item service - allows any module to register menu items with any region
/// </summary>
public class MenuService : IMenuService
{
private IUnityContainer m_UnityContainer;
private IRegionManager m_RegionManager;
private Dictionary<string, IUnityContainer> m_MenuContainers = new Dictionary<string,IUnityContainer>();
/// <summary>
/// Injection ctor
/// </summary>
/// <param name="unityContainer"></param>
/// <param name="regionManager"></param>
public MenuService(IUnityContainer unityContainer, IRegionManager regionManager)
{
m_UnityContainer = unityContainer;
m_RegionManager = regionManager;
}
/// <summary>
/// Registers a menu item with the service
/// </summary>
/// <param name="topLevelName"></param>
/// <param name="regionIdentity"></param>
/// <param name="displayText"></param>
public void RegisterMenuItem(string topLevelName, string regionIdentity, string displayText)
{
IUnityContainer container = GetOrCreateUiIdentityContainer(regionIdentity);
if (string.IsNullOrEmpty(topLevelName))
container.RegisterInstance("MENUITEM" + displayText, new MenuItem { Header = displayText} );
else
{
MenuItem topLevel = container.Resolve<MenuItem>("MENUITEM" + topLevelName);
if (topLevel.Header == null)
{
topLevel = new MenuItem{ Header = topLevelName};
container.RegisterInstance<MenuItem>("MENUITEM" + topLevelName, topLevel);
}
MenuItem newItem = new MenuItem{Header = displayText};
topLevel.Items.Add(newItem);
container.RegisterInstance("MENUITEM" + topLevelName + "_" + displayText, newItem);
}
}
private IUnityContainer GetOrCreateUiIdentityContainer(string regionIdentity)
{
IUnityContainer container;
container = GetUnityContainer(regionIdentity);
if (container != null)
return container;
container = m_UnityContainer.CreateChildContainer();
m_MenuContainers.Add(regionIdentity, container);
return container;
}
private IUnityContainer GetUnityContainer(string regionIdentity)
{
IUnityContainer container;
m_MenuContainers.TryGetValue(regionIdentity, out container);
return container;
}
/// <summary>
/// Builds up the menu for a given region
/// </summary>
/// <param name="regionIdentity"></param>
public void BuildMenu(string regionIdentity)
{
IUnityContainer container;
container = GetUnityContainer(regionIdentity);
if (container == null)
return;
IRegion region = m_RegionManager.Regions[regionIdentity];
if (region == null)
return;
IEnumerable<MenuItem> menuItems = container.ResolveAll<MenuItem>();
foreach (MenuItem item in menuItems)
{
if (item.Role == MenuItemRole.SubmenuHeader )
region.Add(item);
}
}
}
Is there a better way to do what I am trying to do?
Cheers,
Jason
I've got a sample you can take a look at that does exactly this. Hopefully this will help you out a bit. If you have any specific questions after looking at it, let me know!
http://dl.getdropbox.com/u/376992/CAGMenus.zip
Hope this helps.