How to get the name of a dependency property - c#

For binding purposes, we have a method that returns the most common dependency property for the framework element that was passed in. If we pass in TextBlock, this method returns TextBlock.TextProperty; RadMaskedTextBox returns RadMaskedTextBox.MaskedTextProperty, and so on.
While debugging, if type dp.Name, I get "Text", "MaskedText" respectively. But the dp.Name is not available in code.
I'm trying to do dynamic binding to a tooltip:
var binding = new Binding("Text") //Works
{
Source = frameworkElement
};
var binding = new Binding("MaskedText") //Works
{
Source = frameworkElement
};
var binding = new Binding(dp.Name) //Doesn't work
{
Source = frameworkElement
};
I can't figure out how to get "Text" or "MaskedText" from the dependency property, nor do I understand why it's hidden to begin with.
.Net Framework 4.5 / Silverlight 5
Thanks for any help or insight you can give!!
JD
Kevin, Thank you so much, you were pretty close. It's a non-public field, so I did this:
{
var dpType = dp.GetType();
var nameField = dpType
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Single(pi => pi.Name == "Name");
var name = nameField.GetValue(dp);
}
However, I get an FieldAccessViolation when I call nameField.GetValue(dp). I can see it in the watch, but can't actually get to it. I wish someone would explain this, because I don't understand why I should not be able to get/use this value. Especially when that (the string "MaskedText") is what has to supplied for the path. UGH!!!
But thank you very much for your help!
JD

I'm not 100% sure what is going on without further clarification... But making some assumptions it should be possible to get the name via reflection...
var typeOfDp = dp.GetType();
var nameProperty = typeOfDp
.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Single(t => t.Name == "Name");
var name = nameProperty.GetValue(dp);
var binding = new Binding(name) //Maybe it will work?
{
Source = frameworkElement
};

Related

How do I create and manipulate a Table property for an IFC object using Xbim?

I am working off of the basic example for amending data (https://github.com/xBimTeam/XbimEssentials). The only thing I'm changing is within the code below, where I want to add an IfcPropertyTableValue instead of an IfcPropertySingleValue.
This code runs, but in XbimXplorer under the object's properties, nothing's there - it's blank.
To make sure, the example code, as well as other property types do work and do show up in Xplorer under properties.
var pSetRel = model.Instances.New<IfcRelDefinesByProperties>(r =>
{
r.GlobalId = Guid.NewGuid();
r.RelatingPropertyDefinition = model.Instances.New<IfcPropertySet>(pSet =>
{
pSet.Name = "Points";
// FOR EACH POINT i :
pSet.HasProperties.Add(model.Instances.New<IfcPropertyTableValue>(p =>
{
p.Name = "Points " + i;
// FOR EACH COORDINATE x :
p.DefiningValues.Add(new IfcText(x));
p.DefinedValues.Add(new IfcReal(-3.25));
}));
});
});
How can I make this work?
I have also tried using code to read the property, in case XbimXplorer just doesn't display tables. This code runs and prints zero lines (but works for other properties that are displayed in Xplorer):
// Try to read and print the new property
var nameObj = "my_object_name";
var checkObj = model.Instances.FirstOrDefault<IIfcBuildingElement>(d => d.Name == nameObj);
if (checkObj == null)
{
outputBox.AppendText(newLine + "Object: " + nameObj + " not found");
}
else
{
var properties = checkObj.IsDefinedBy
.Where(r => r.RelatingPropertyDefinition is IIfcPropertySet)
.SelectMany(r => ((IIfcPropertySet)r.RelatingPropertyDefinition).HasProperties)
.OfType<IIfcPropertySingleValue>();
foreach (var property in properties)
outputBox.AppendText($"Property: {property.Name}, Value: {property.NominalValue}");
}
It would also be convenient if I could add several defining/defined value pairs at once, for instance like this (similar to normal C# lists):
IEnumerable<IfcValue> definingValues = new IfcText() {"x", "y", "z", "k"};
p.DefinedValues.AddRange(definingValues);
IEnumerable<IfcValue> definedValues = new IfcReal() {0.0, 1.6, -2.5, 3.33};
p.DefinedValues.AddRange(definedValues);
However, {"x", "y", "z", "k"} is then marked with the error Cannot initialize type 'IfcText' with a collection initializer because it does not implement 'System.Collections.IEnumerable'.
I don't think xbim Xplorer displays IfcPropertyTableValues. Probably because very few BIM tools currently output TableValues so I guess it never got implemented (and you'd need to establish how to display the table in the Xplorer view - do you nest a table in a property grid?).
If you look at the Xplorer code you'll see it only supports SingleValues, ComplexValues and EnumeratedValues. You might be able to use Complex Values as a collection of multiple IfcPropertySingleValues as a workaround.
In your 2nd code sample to output the values, you're filtering out any IfcPropertyTableValues with the .OfType<IIfcPropertySingleValue>() clause so you'll never see the output. Take a look at the IFC specs for SimpleProperties: https://standards.buildingsmart.org/IFC/RELEASE/IFC4_1/FINAL/HTML/link/ifcsimpleproperty.htm
On the last question you're initializing the array with the wrong syntax. Try something like this:
var labels = new Ifc4.MeasureResource.IfcText[] { "x", "y" };
p.DefiningValues.AddRange(labels.Cast<IIfcValue>());

Unable to save lists to MongoDB using UpdateDefinitionBuilder in C#

I have the following helper function that uses reflection to look at the supplied model, check if any fields are non-null, and overwrite those with new values in MongoDB.
It works fine until I try updating a List<string> field. Instead of saving the list as an array to MongoDB, it saves a string value of "(Collection)" in MongoDB. What am I missing to make this work?
I don't want to hardcode that any List should default to List<string> either. It's possible I could have lists of ints.
public override MyObj Update(MyObj model)
{
var builder = Builders<MyObj>.Update;
var builder_def = builder.Set(x => x.Id, model.Id);
foreach (PropertyInfo prop in model.GetType().GetProperties())
{
var value = model.GetType().GetProperty(prop.Name).GetValue(model, null);
if (value != null)
{
builder_def = builder_def.Set(prop.Name, value); // Not setting lists correctly
}
}
var filter = Builders<MyObj>.Filter;
var filter_def = filter.Eq(x => x.Id, model.Id);
Connection.Update(filter_def, builder_def);
return model;
}
Edit
I think my problem is related to this open bug https://jira.mongodb.org/browse/CSHARP-1984. Given that, is there any way for me to make this work in that context?

object' does not contain a definition for MainTypeCode for dynamic data

This below query return some mock data for unit testing.
var colorsList = (IEnumerable<dynamic>)colorsRepository.GetColorsList().Result;
It given the result as dynamic object
I want to get MainTypeCode value only. But it is showing object' does not contain a definition for MainTypeCode
colorsList.Select(cl => (dynamic)cl.MainTypeCode);
Edit:
And let me know how to arrange dummy/mock dynamic data to execute the query?
and colorsRepository.GetColorsList().Result; is returning below way. Shall I change the mock data to run the query?
public static IEnumerable<dynamic> GetColorsList()
{
List<dynamic> colours = new List<dynamic>();
for (int i = 0; i < 1; i++)
{
colours.Add((dynamic)new
{
MainTypeCode = 1,
DoorCode = "001"
});
}
return colours.AsEnumerable();
}
I'm guessing, the issue might be related with the dynamic. Could you try something like the following?
var colorLists = new [] { new {DoorCode = "001", MainTypeCode = 1}, new {DoorCode = "002", MainTypeCode = 2}};
var mainTypeCodes = colorLists.Select(cl => cl.GetType().GetProperty("MainTypeCode").GetValue(cl, null));
Get value of c# dynamic property via string
Sadly I have much time to elaborate a better answer, but you will have to use reflection in order to get the dynamic properties.
If you know the dynamic properties before hand you can try to do a class and create a Map method with reflection to get the object.

Sitefinity: Dynamic Content query optimization with field values

I will attempt to be as specific as possible. So we are using Sitefinity 8.1.5800, I have a couple dynamic content modules named ReleaseNotes and ReleaseNoteItems. ReleaseNotes has some fields but no reference to ReleaseNoteItems.
Release Note Items has fields and a related data field to ReleaseNotes.
So I can query all ReleaseNoteItems as dynamic content pretty quickly less than a second.
I then use these objects provided by sitefinity and map them to a C# object so I can use strong type. This mapping process is taking almost a minute and using over 600 queries for only 322 items (N+1).
In Short: I need to get all sitefinity objects and Map them to a usable c# object quicker than I currently am.
The method for fetching the dynamic content items (takes milliseconds):
private IList<DynamicContent> GetAllLiveReleaseNoteItemsByReleaseNoteParentId(Guid releaseNoteParentId)
{
DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(String.Empty);
Type releasenoteitemType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.ReleaseNoteItems.Releasenoteitem");
string releaseNoteParentTypeString = "Telerik.Sitefinity.DynamicTypes.Model.ReleaseNotes.Releasenote";
var provider = dynamicModuleManager.Provider as OpenAccessDynamicModuleProvider;
int? totalCount = 0;
var cultureName = "en";
Thread.CurrentThread.CurrentUICulture = new CultureInfo(cultureName);
Type releasenoteType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.ReleaseNotes.Releasenote");
// This is how we get the releasenote items through filtering
DynamicContent myCurrentItem = dynamicModuleManager.GetDataItem(releasenoteType, releaseNoteParentId);
var myMasterParent =
dynamicModuleManager.Lifecycle.GetMaster(myCurrentItem) as DynamicContent;
var relatingItems = provider.GetRelatedItems(
releaseNoteParentTypeString,
"OpenAccessProvider",
myMasterParent.Id,
string.Empty,
releasenoteitemType,
ContentLifecycleStatus.Live,
string.Empty,
string.Empty,
null,
null,
ref totalCount,
RelationDirection.Parent).OfType<DynamicContent>();
IList<DynamicContent> allReleaseNoteItems = relatingItems.ToList();
return allReleaseNoteItems;
}
This is the method that takes almost a minute that is mapping sitefinity object to C# object:
public IList<ReleaseNoteItemModel> GetReleaseNoteItemsByReleaseNoteParent(ReleaseNoteModel releaseNoteItemParent)
{
return GetAllLiveReleaseNoteItemsByReleaseNoteParentId(releaseNoteItemParent.Id).Select(rn => new ReleaseNoteItemModel
{
Id = rn.Id,
Added = rn.GetValue("Added") is bool ? (bool)rn.GetValue("Added") : false,
BugId = rn.GetValue<string>("bug_id"),
BugStatus = rn.GetValue<Lstring>("bugStatus"),
Category = rn.GetValue<Lstring>("category"),
Component = rn.GetValue<Lstring>("component"),
#Content = rn.GetValue<Lstring>("content"),
Criticality = rn.GetValue<Lstring>("criticality"),
Customer = rn.GetValue<string>("customer"),
Date = rn.GetValue<DateTime?>("date"),
Grouped = rn.GetValue<string>("grouped"),
Override = rn.GetValue<string>("override"),
Patch_Num = rn.GetValue<string>("patch_num"),
PublishedDate = rn.PublicationDate,
Risk = rn.GetValue<Lstring>("risk"),
Title = rn.GetValue<string>("Title"),
Summary = rn.GetValue<Lstring>("summary"),
Prod_Name = rn.GetValue<Lstring>("prod_name"),
ReleaseNoteParent = releaseNoteItemParent,
McProductId = GetMcProductId(rn.GetRelatedItems("McProducts").Cast<DynamicContent>()),
}).ToList();
}
Is there any way to optimize this all into one query or a better way of doing this? Taking almost a minute to map this objects is too long for what we need to do with them.
If there is no way we will have to cache the items or make a SQL query. I would rather not do caching or SQL query if I do not have to.
Thank you in advance for any and all help you can provide, I am new to posting questions on stackoverflow so if you need any additional data please let me know.
Is there a reason why you are doing a .ToList() for the items? Is it possible for you to avoid that. In my opinion, most of the time(of the 1 minute) is taken to convert all your items into a list. Conversion from Sitefinity object to C# object is not the culprit here.
Look Arno's answer here: https://plus.google.com/u/0/112295105425490148444/posts/QrsVtxj1sCB?cfem=1
You can use the "Content links manager" to query dynamic modules relationships (both by parent -ParentItemId- or by child -ChildItemId-) much faster:
var providerName = String.Empty;
var parentTitle = "Parent";
var relatedTitle = "RelatedItem3";
DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(providerName);
Type parentType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.ParentModules.ParentModule");
Type relatedType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.RelatedModules.RelatedModule");
ContentLinksManager contentLinksManager = ContentLinksManager.GetManager();
// get the live version of all parent items
var parentItems = dynamicModuleManager.GetDataItems(parentType).Where(i => i.GetValue<string>("Title").Contains(parentTitle) && i.Status == ContentLifecycleStatus.Live && i.Visible);
// get the ids of the related items.
// We use the OriginalContentId property since we work with the live vesrions of the dynamic modules
var parentItemIds = parentItems.Select(i => i.OriginalContentId).ToList();
// get the live versions of all the schedules items
var relatedItems = dynamicModuleManager.GetDataItems(relatedType).Where(i => i.Status == ContentLifecycleStatus.Live && i.Visible && i.GetValue<string>("Title").Contains(relatedTitle));
// get the content links
var contentLinks = contentLinksManager.GetContentLinks().Where(cl => cl.ParentItemType == parentType.FullName && cl.ComponentPropertyName == "RelatedField" && parentItemIds.Contains(cl.ParentItemId) && cl.AvailableForLive);
// get the IDs of the desired parent items
var filteredParentItemIds = contentLinks.Join<ContentLink, DynamicContent, Guid, Guid>(relatedItems, (cl) => cl.ChildItemId, (i) => i.OriginalContentId, (cl, i) => cl.ParentItemId).Distinct();
// get the desired parent items by the filtered IDs
var filteredParentItems = parentItems.Where(i => filteredParentItemIds.Contains(i.OriginalContentId)).ToList();
I would imagine that every release note item under a single release note would be related to the same product wouldn't it?
If so, do you need to do the GetMcProductId method for every item?

Help with EntityQuery working Silverlight C#

I have the following code:
var data = (sender as Button).DataContext as Web.Booking;
EntityQuery<Web.Ticket> ticketQuery =
from t in _ticketContext.GetTicketsQuery()
where t.ticketId == data.ticketId
select t;
LoadOperation<Web.Ticket> loadTicket = this._ticketContext.Load(ticketQuery);
loadTicket.Completed += (s, args) => { MessageBox.Show("Loaded Tickets!"); };
ticketDomainDataSource.DataContext = loadTicket.AllEntities;
var ticketData = ticketDomainDataSource.DataContext as Web.Ticket;
string ticketName = ticketData.ticketName;
The main code that I'm having trouble with is the:
var ticketData = ticketDomainDataSource.DataContext as Web.Ticket;
string ticketName = ticketData.ticketName;
It returns an error:
Object reference not set to an
instance of an object.
Can anyone help me out on what I'm doing wrong here, I can't figure out what's null and how I can return proper data.
Thanks
Your issue is likely that DataContext cannot be cast to Web.Ticket. If you look at the documentation for C# -- as returns a null on a conversion failure. See - http://msdn.microsoft.com/en-us/library/cscsdfbt%28v=vs.71%29.aspx
If you change your line of code to
var ticketData = (Web.Ticket) ticketDomainDataSource.DataContext;
you should get a better cast error.

Categories