Retrieving child from a Foreign Key in Salesforce - foreign-keys

I've a parent object (Product) and a child (Inventory). I'm trying to retrieve the value of the child object from a DisplayProducts class that I've created.
public class DisplayProducts {
private Product__c products;
public DisplayProducts(Product__c item) {
this.products = item;
}
// Properties for use in the Visualforce view
public String name {
get { return products.Name; }
}
public String colour {
//error here
get { return products.Inventorys__r.Colour__c; }
}
public class Product {
public List<DisplayProducts> getProducts() {
if(products == null) {
products = new List<DisplayProducts>();
for(Product__c item : [Select ProductID__c,Name, Price__c, (SELECT Inventory__c.Size__c, Inventory__c.Colour__c, Inventory__c.Quantity__c FROM Product__c.Inventorys__r)
From Product__c WHERE ProductID__c = :prodID]) {
products.add(new DisplayProducts(item));
}
}
return products;
}
}
I keep getting a compile error: invalid FK relationship.
I tried
products.Inventorys__r[0].Colour__c;
but it will only retrieved the first element.
How do I retrieve the child item via the DisplayProducts Class? Any help will be greatly appreciated.
Thank you.

Related

How to display grouped list of values in Xamarin?

I am trying to display grouped list of songs, which I get from server. Songs are grouped in sets according to their first letter. I've created two classes in this purpose SongSet and Song.
public class SongSet
{
public string FirstCharacter { get; set; }
public List<Song> ListOfSongs { get; set; } = new List<Song>();
public SongSet(string firstChar)
{
this.FirstCharacter = firstChar;
}
}
public class Song
{
public string SongTitle { get; set; }
public Song(string title)
{
this.SongTitle = title;
}
}
After received list from server I put it to list of SongSet objects.
public static List<SongSet> ListOfSongsFromServer { get; set; } = new List<SongSet>();
And here my code to display a whole list.
ListView listView = new ListView
{
IsGroupingEnabled = true,
GroupDisplayBinding = new Binding("FirstCharacter"),
ItemsSource = PlayerPageVM.ListOfSongsFromServer,
ItemTemplate = new DataTemplate(() =>
{
Label titleLabel = new Label();
titleLabel.SetBinding(Label.TextProperty, "SongTitle");
return new ViewCell
{
View = new StackLayout
{
Padding = new Thickness(0, 5),
Orientation = StackOrientation.Horizontal,
Children =
{
new StackLayout
{
VerticalOptions=LayoutOptions.Center,
Spacing=0,
Children =
{
titleLabel
}
}
}
}
};
})
};
this.Content = new StackLayout
{
Children =
{
listView
}
};
After build application I've received only list with first letters but without song titles uder them. Can anyone help me how to achievie this?
You want to display grouped list of songs, you could use CollectionView. Because it provides the easy way to show Group data.
Display grouped data:
<CollectionView ItemsSource="{Binding Animals}"
IsGrouped="true">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
...
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
And the problem of mode data could refer to document to make SongSet inherit from Lsit<Song> to generate a grouped data.
public class SongSet : List<Song>
{
public string FirstCharacter { get; set; }
public SongSet(string firstChar,List<Song> ListOfSongs): base(ListOfSongs)
{
this.FirstCharacter = firstChar;
}
}

How to enable VersionCountDisabler for Glass Mapper in Sitecore for SitecoreQuery and SitecoreChildren attributes

The glass mapper will return null object or (no items) for SitecoreQuery and SitecoreChildren attribute that are placed on the GlassModels. These attributes don't take any such parameter where I can specify them to return items if they don't exist in the the context lanaguge. The items e.g. exist in EN but don't exist in en-ES. I need to put a lot of null check in my views to avoid Null exception and makes the views or controller very messy. It is lot of boiler plate code that one has to write to make it work.
In Page Editor the SitecoreChildren returns item and content authors can create items in that langauge version by editing any field on the item. This automatically creates the item in that langauge. However the same code will fail in Preview mode as SitecoreChidren will return null and you see null pointer exception.
SitecoreQuery doesn't return any items in page editor and then Content Authors wont be able to create items in Page editor.
To make the experience good if we can pass a parameter to SiteocreQuery attribute so it disable VsersionCount and returns the items if they dont exist in that langauge.
This is actually not possible. There is an issue on GitHub which would make it easy to create a custom attribute to handle this very easy. Currently you need to create a new type mapper and copy all the code from the SitecoreQueryMapper. I have written a blog post here about how you can create a custom type mapper. You need to create the following classes (example for the SitecoreQuery).
New configuration:
public class SitecoreSharedQueryConfiguration : SitecoreQueryConfiguration
{
}
New attribute:
public class SitecoreSharedQueryAttribute : SitecoreQueryAttribute
{
public SitecoreSharedQueryAttribute(string query) : base(query)
{
}
public override AbstractPropertyConfiguration Configure(PropertyInfo propertyInfo)
{
var config = new SitecoreSharedQueryConfiguration();
this.Configure(propertyInfo, config);
return config;
}
}
New type mapper:
public class SitecoreSharedQueryTypeMapper : SitecoreQueryMapper
{
public SitecoreSharedQueryTypeMapper(IEnumerable<ISitecoreQueryParameter> parameters)
: base(parameters)
{
}
public override object MapToProperty(AbstractDataMappingContext mappingContext)
{
var scConfig = Configuration as SitecoreQueryConfiguration;
var scContext = mappingContext as SitecoreDataMappingContext;
using (new VersionCountDisabler())
{
if (scConfig != null && scContext != null)
{
string query = this.ParseQuery(scConfig.Query, scContext.Item);
if (scConfig.PropertyInfo.PropertyType.IsGenericType)
{
Type outerType = Glass.Mapper.Sc.Utilities.GetGenericOuter(scConfig.PropertyInfo.PropertyType);
if (typeof(IEnumerable<>) == outerType)
{
Type genericType = Utilities.GetGenericArgument(scConfig.PropertyInfo.PropertyType);
Func<IEnumerable<Item>> getItems;
if (scConfig.IsRelative)
{
getItems = () =>
{
try
{
return scContext.Item.Axes.SelectItems(query);
}
catch (Exception ex)
{
throw new MapperException("Failed to perform query {0}".Formatted(query), ex);
}
};
}
else
{
getItems = () =>
{
if (scConfig.UseQueryContext)
{
var conQuery = new Query(query);
var queryContext = new QueryContext(scContext.Item.Database.DataManager);
object obj = conQuery.Execute(queryContext);
var contextArray = obj as QueryContext[];
var context = obj as QueryContext;
if (contextArray == null)
contextArray = new[] { context };
return contextArray.Select(x => scContext.Item.Database.GetItem(x.ID));
}
return scContext.Item.Database.SelectItems(query);
};
}
return Glass.Mapper.Sc.Utilities.CreateGenericType(typeof(ItemEnumerable<>), new[] { genericType }, getItems, scConfig.IsLazy, scConfig.InferType, scContext.Service);
}
throw new NotSupportedException("Generic type not supported {0}. Must be IEnumerable<>.".Formatted(outerType.FullName));
}
{
Item result;
if (scConfig.IsRelative)
{
result = scContext.Item.Axes.SelectSingleItem(query);
}
else
{
result = scContext.Item.Database.SelectSingleItem(query);
}
return scContext.Service.CreateType(scConfig.PropertyInfo.PropertyType, result, scConfig.IsLazy, scConfig.InferType, null);
}
}
}
return null;
}
public override bool CanHandle(AbstractPropertyConfiguration configuration, Context context)
{
return configuration is SitecoreSharedQueryConfiguration;
}
}
And configure the new type mapper in your glass config (mapper and parameters for the constructor):
container.Register(Component.For<AbstractDataMapper>().ImplementedBy<SitecoreSharedQueryTypeMapper>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemPathParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemIdParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemIdNoBracketsParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemEscapedPathParameter>>().LifeStyle.Transient);
container.Register(Component.For<IEnumerable<ISitecoreQueryParameter>>().ImplementedBy<List<ItemDateNowParameter>>().LifeStyle.Transient);
You can then simply change the SitecoreQuery attribute on your model to SitecoreSharedQuery:
[SitecoreSharedQuery("./*")]
public virtual IEnumerable<YourModel> YourItems { get; set; }
For the children you could either use the shared query mapper and querying the children or create the same classes for a new SitecoreSharedChildren query.
Edit: Added bindings for IEnumerable<ISitecoreQueryParameter> as they are missing and therefor it threw an error.

How to get distinct records from a list

I have a list of type Myclass
List<Myclass> liSubjectIdDetail = new List<Myclass>();
where Myclass looks like
public class Myclass
{
public Nullable<decimal> SubjectId { get; set; }
public string SubjectName { get; set; }
}
I am adding records into liSubjectIdDetail from a table
foreach (decimal Id in VarCEMSIdDetail)
{
liSubjectIdDetail.AddRange(db.Stt.MyTable.Where(x => x.Id == Id).Select(x => new Myclass { SubjectId = x.SubjectId, SubjectName = x.SubjectName }).ToList());
}
where Id contains a list of certain Ids on the basis of which records I fetch.
Now I want to get only distinct records in this list.
I have tried it with hashtable in place of List
and I also tried
liSubjectIdDetail= liSubjectIdDetail.Distinct().ToList();
but this too, is not working. Please give me a better solution.
Thanks in advance
Try this extension method
public static class IEnumerableExtensions {
public static IEnumerable<TSource> DistinctBy<TSource, TKey>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
var seenKeys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (seenKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
}
Usage:
liSubjectIdDetail= liSubjectIdDetail.DistinctBy(s => s.SubjectName).ToList();

Silverlight: Parent ViewModel Property value to Child ViewModel property

I posted this question on the Silverlight forums, but haven't been able to get an answer to solve my issue, so I hope the guru's at SO can help!
Basically I have an entity property in my parent viewmodel. When this entity changes I need the ID of the entity in my child viewmodel. I have created a child control with a dependency property and created a binding in the constructor. I am trying to implement all this using MVVM and MEF.
My ParentViewModel:
[ExportPlugin(ViewModelTypes.ParentViewModel, PluginType.ViewModel)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ParentViewModel: ViewModelBase
{
private Person _currentPerson;
public Person CurrentPerson
{
get { return _currentPerson; }
private set
{
if (!ReferenceEquals(_currentPerson, value))
{
_currentPerson= value;
RaisePropertyChanged("CurrentPerson");
}
}
}
}
My ParentUserControl:
<UserControl x:Class="MyApp.ParentUserControl" x:Name="ParentControl">
<local:ChildUserControl PersonID="{Binding ElementName=ParentControl, Mode=TwoWay, Path=DataContext.CurrentPerson.ID}" />
</UserControl>
My ChildUserControl codebehind:
public partial class ChildUserControl : UserControl
{
#region Private Properties
private PluginCatalogService _catalogService = PluginCatalogService.Instance;
#endregion
#region Dependency Properties
public static readonly DependencyProperty PersonIDProperty =
DependencyProperty.Register("PersonID", typeof(int), typeof(ChildUserControl), new PropertyMetadata(OnPersonIDChanged));
#endregion
#region Public Properties
public int PersonID
{
get { return (int)GetValue(PersonIDProperty); }
set { SetValue(PersonIDProperty, value); }
}
#endregion
#region Constructor
public ChildUserControl()
{
InitializeComponent();
if (!ViewModelBase.IsInDesignModeStatic)
this.DataContext = _catalogService.FindPlugin(ViewModelTypes.ChildViewModel, PluginType.ViewModel);
this.SetBinding(PersonIDProperty, new Binding("PersonID") { Mode = BindingMode.TwoWay, Source = DataContext, UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
}
#endregion
private static void OnPersonIDChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
...
}
My ChildViewModel:
[ExportPlugin(ViewModelTypes.ChildViewModel, PluginType.ViewModel)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChildViewModel: ViewModelBase
{
private int _personID;
public int PersonID
{
get { return _personID; }
set
{
if (!ReferenceEquals(_personID, value))
{
_personID= value;
RaisePropertyChanged("PersonID");
}
}
}
}
I created the OnPersonIDChanged event to see if when the CurrentPerson entity changed, the change was being picked up in the ChildControl, which it is. It just isn't being picked up in the ChildControl ViewModel.
Any help is much appreciated.
Preferably, if you are using PRISM you can use the EventAggregator...
see http://msdn.microsoft.com/en-us/library/ff921122(v=pandp.40).aspx and https://compositewpf.codeplex.com/
Another option would be to hook (hack) onto the PropertyChanged
ViewModel1.PropertyChanged += (s, e) =>
{
if (e.PropertyName == "XXX")
{
ViewModel2.PropertyX = vm1.PropertY;
}
};

How can I upload image and post some datas to MVC4 wep api method?

I have tried for days but I couldn't reach any successful result. I need to post images with their information (s.t. created user name).
This is my method;
[HttpPost]
public Task<HttpResponseMessage> PostFile(string createdByName)
{
HttpRequestMessage request = this.Request;
if (!request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = System.Configuration.ConfigurationSettings.AppSettings["TempUploadDir"];
var provider = new MultipartFormDataStreamProvider(root);
var task = request.Content.ReadAsMultipartAsync(provider).
ContinueWith<HttpResponseMessage>(o =>
{
AddImages(provider.BodyPartFileNames);
string file1 = provider.BodyPartFileNames.First().Value;
// this is the file name on the server where the file was saved
return new HttpResponseMessage()
{
Content = new StringContent("File uploaded.")
};
}
);
return task;
}
And this my TypeFormatterClass which is added global.asax
public class MultiFormDataMediaTypeFormatter : FormUrlEncodedMediaTypeFormatter
{
public MultiFormDataMediaTypeFormatter()
: base()
{
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));
}
protected override bool CanReadType(Type type)
{
return true;
}
protected override bool CanWriteType(Type type)
{
return false;
}
protected override Task<object> OnReadFromStreamAsync(Type type, Stream stream, HttpContentHeaders contentHeaders, FormatterContext formatterContext)
{
var contents = formatterContext.Request.Content.ReadAsMultipartAsync().Result;
return Task.Factory.StartNew<object>(() =>
{
return new MultiFormKeyValueModel(contents);
});
}
class MultiFormKeyValueModel : IKeyValueModel
{
IEnumerable<HttpContent> _contents;
public MultiFormKeyValueModel(IEnumerable<HttpContent> contents)
{
_contents = contents;
}
public IEnumerable<string> Keys
{
get
{
return _contents.Cast<string>();
}
}
public bool TryGetValue(string key, out object value)
{
value = _contents.FirstDispositionNameOrDefault(key).ReadAsStringAsync().Result;
return true;
}
}
}
When I post images and "createdByName" I can reach images but I couldn't parameters. How can I do this?
Thank you.
To get your createdByName field, inside your ContinueWith :
var parts = o.Result;
HttpContent namePart = parts.FirstDispositionNameOrDefault("createdByName");
if (namePart == null)
{
throw new HttpResponseException(HttpStatusCode.BadRequest);
}
string name = namePart.ReadAsStringAsync().Result;
For a more detailed example, see :
http://www.asp.net/web-api/overview/working-with-http/html-forms-and-multipart-mime#multipartmime