Windows Store App template does not create BooleanToVisibilityConverter in common - visual-studio-2013

I am using VS2013 and creating a windows store app (windows 8.1) from the templates. Many references show that there is a BooleanToVisibilityConverter class being created in the common folder that can be referenced it the xaml but the class is not created in my common folder. I get NavigationHelper, ObservableDictionary, RelayCommand, and SuspensionManager but not BooleanToVisibilityConverter.
So what am I missing about this?

Templates can be changed from version to version. So, create it by hands:
public sealed class BooleanToVisibilityConverter : IValueConverter
{
public object Convert( object value, Type targetType, object parameter, string language )
{
return ( value is bool && ( bool )value ) ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack( object value, Type targetType, object parameter, string language )
{
return value is Visibility && ( Visibility )value == Visibility.Visible;
}
}

Related

Sitecore7 Linq to Sitecore only works with SearchResultItem but not with Custom Mapped Class

I have this very weird problem that I cannot get my head around. Perhaps someone could point out what I am doing wrong.
Basically, I am just trying to search items using Linq to Sitecore.
So, my classes look like ( I am using glass too)
[SitecoreType(TemplateId = "{TEMPLATE_GIUD}")]
public class MyMappedClass : SharedFieldClass
{
[SitecoreField(FieldName = "mylist")]
public virtual IEnumerable<SharedFieldClass> MyMultilistField { get; set; }
[SitecoreField(FieldName = "field1")]
[IndexField("field1")]
public virtual MyKeyValue field1 { get; set; }
}
[SitecoreType]
public class MyKeyValue
{
public virtual Sitecore.Data.ID Id {get;set;}
public virtual string MyValue{get;set;}
}
So when I do the below query it works as it's supposed to.
var results = context.GetQueryable<SearchResultItem>()
.Where(c => ((string)c["field1"]) == "{GUID}").GetResults();
But, when I do the below it returns 0 result.
List<MyMappedClass> results = context.GetQueryable<MyMappedClass>()
.Where(c => c.field1.MyValue == "{GUID}").ToList();
I have read this link . And I have followed the 2nd process described here for Glass to work with Sitecore7 Search (the "SharedFieldClass" contains all the basic index fields).
This is a pretty obvious scenario and I'm sure lots of people have done it already and I am doing something silly here.
Thanks in advance.
/## EDIT ##/
Okay so I've done a bit more digging on this. Not sure if it's a bug in ContentSearch/Luncene.NET API or I am missing something BUT seems like what was posted here is probably not TRUE and if you have a complex field type ( which you will ) you can not query with a mapped class against Lucene. ( not sure if this is also the case for Solr). If you are doing search against simple type like string and int then it works like a charm.
SO here're my findings:
After enabling DEBUG and LOG on for contentsearch I found that if I query like this context.GetQueryable<MyMappedClass>().Where(c => c.field1.MyValue == "{GUID}") what it gets translated into is DEBUG Executing lucene query: field1.value:7e9ed2ae07194d83872f9836715eca8e and as there's no such thing in the index named "field1.value" the query doesn't return anything. The name of the index is actually just "field1". Is this a bug ??
However, query like this context.GetQueryable<SearchResultItem>() .Where(c => ((string)c["field1"]) == "{GUID}").GetResults(); works because it gets translated into "DEBUG Executing lucene query: +field1:7e9ed2ae07194d83872f9836715eca8e".
I also did write a method in my mapped class like below:
public string this[string key]
{
get
{
return key.ToLowerInvariant();
}
set { }
}
Which allowed me write the below query with my MyMappedClass.
results2 = context.GetQueryable<MyMappedClass>().Where(c => c["filed1"]== "{GUID}").ToList();
This returned expected result. BUT the values of the fields in MyMappedClass are not filled ( in fact they're all null except the core/shared values like templateid, url etc which are populated in the filled document). So the result list are pretty much useless. I could do a loop over all of them and manually get the values populated as I have the itemid. But imagine the cost for a large result set.
Lastly I did this:
<fieldType fieldTypeName="droplink" storageType="YES" indexType="TOKENIZED" vectorType="NO" boost="1f" type="System.String" settingType="Sitecore.ContentSearch.LuceneProvider.LuceneSearchFieldConfiguration, Sitecore.ContentSearch.LuceneProvider" />
So this returned populated "field1" with the itemid in lucene query using "IndexViewer2.0". BUT this fails for MyMappedClass too as the value of "field1" in the document is a System.string .. but it is mapped as "MyKeyValue" in MyMappedClass SO it throws the below exception
Exception: System.InvalidCastException
Message: Invalid cast from 'System.String' to 'MyLib.MyKeyValue'.
SO, the big question is:
How does one query using his/her mapped class using the cool ContentSearch API ?
I bit more further digging got me to a working solution. Posting it here just in case anyone runs into this issue.
This is how my "SharedFieldClass" looked like ( which was somewhat wrong )
public abstract class SharedFieldClass
{
[SitecoreId]
[IndexField("_id")]
[TypeConverter(typeof(IndexFieldIDValueConverter))]
public virtual ID Id { get; set; }
[SitecoreInfo(SitecoreInfoType.Language)]
[IndexField("_language")]
public virtual string Language { get; set; }
[SitecoreInfo(SitecoreInfoType.Version)]
public virtual int Version
{
get
{
return Uri == null ? 0 : Uri.Version.Number;
}
}
[TypeConverter(typeof(IndexFieldItemUriValueConverter))]
[XmlIgnore]
[IndexField("_uniqueid")]
public virtual ItemUri Uri { get; set; }
}
And there's a class in Glass that does the mapping. Which looks like below:
var sitecoreService = new SitecoreService("web");
foreach (var r in results)
{
sitecoreService.Map(r);
}
for me this class was failing to map because of this line:
[SitecoreId]
[IndexField("_id")]
[TypeConverter(typeof(IndexFieldIDValueConverter))]
public virtual ID Id { get; set; }
It was throwing a NULL exception at sitecoreService.Map(r); line
So I changed it to below:
[SitecoreId]
[IndexField("_group")]
[TypeConverter(typeof(IndexFieldIDValueConverter))]
public virtual ID Id { get; set; }
And it worked. I'm not sure when the index field for ItemId in sitecore changed from "_id" to "_group" or whether it was always like that. But it is "_group" in the SearchResultItem class. So I used it and mapping was successful.
So to Sum it all the solution looks like this:
The Mapped Class:
[SitecoreType(TemplateId = "{TEMPLATE_GIUD}")]
public class MyMappedClass : SharedFieldClass
{
[SitecoreField(FieldName = "mylist")]
public virtual IEnumerable<SharedFieldClass> MyMultilistField { get; set; }
[SitecoreField(FieldName = "field1")]
[IndexField("field1")]
public virtual MyKeyValue field1 { get; set; }
// Will be set with key and value for each field in the index document
public string this[string key]
{
get
{
return key.ToLowerInvariant();
}
set { }
}
}
[SitecoreType]
public class MyKeyValue
{
public virtual Sitecore.Data.ID Id {get;set;}
public virtual string MyValue{get;set;}
}
And the query is:
List<MyMappedClass> results = context.GetQueryable<MyMappedClass>()
.Where(c => c["field1"] == "{GUID}").ToList();
That's it.
/* edited */
OH!! Wait that's not it. This will still fail to cast the complex type "MyKeyValue" when the "field1" is populated with guid in the index document.
So to avoid this I had to write my custom converter as #Michael Edwards suggested.
I had to modify the class slightly to fit my needs ..
public class IndexFieldKeyValueModelConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
var config = Glass.Mapper.Context.Default.GetTypeConfiguration<SitecoreTypeConfiguration>(sourceType, true);
if (config != null && sourceType == typeof(MyLib.IKeyValue))
{
return true;
}
else
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;
else
return base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var scContext = new SitecoreContext();
Guid x = Guid.Empty;
if(value is string)
{
x = new Guid((string)value);
}
var item = scContext.Database.GetItem(x.ToString());
if (item == null)
return null;
return scContext.CreateType(typeof(MyLib.IKeyValue), item, true, false, new Dictionary<string, object>());
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
var config = Glass.Mapper.Context.Default.GetTypeConfiguration<SitecoreTypeConfiguration>(value.GetType(), true);
ID id = config.GetId(value);
return id.ToShortID().ToString().ToLowerInvariant();
}
}
Not sure if it were the expected behaviour or not .. but for some reason, in the convertfrom method the value of the "object value" parameter was short string id format. So for scContext.Database.GetItem to work I had to convert it to a proper GUID and then it started returning proper item rather than null.
AND then I wrote my query like this:
results = context.GetQueryable<MyMappedGlassClass>().Where(c => c["field1"] == field1value && c["field2"] == field2value && c["_template"] == templateId).Filter(selector => selector["_group"] != currentId).ToList();
Looks like a fair bit of work to get it to work. I guess using the LinqHelper.CreateQuery method is the easy way out .. but as Mr. Pope suggested here that this method is not be used as this is an internal method.
Not sure what's the balance here.
/* end edited */
Please see my question description section for explanation on why I had to do things this way.
Also, (I bias opinion ) is the trick described here may not be valid anymore (please see my question description's edit section for the reason behind).
Also, index field for itemid in the Glass Mapper tutorial here is I think wrong (unless otherwise proven).
Hope it helps someone saving/wasting time.
You could create a custom field mapper for lucene that would convert from the Guid in the index to a glass model. I hacked this out but I haven't tested it:
public class IndexFieldDateTimeValueConverter : TypeConverter
{
public Type RequestedType { get; set; }
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
var config = Glass.Mapper.Context.Default.GetTypeConfiguration<SitecoreTypeConfiguration>(sourceType, true);
if (config != null)
{
RequestedType = sourceType;
return true;
}
else
return base.CanConvertFrom(context, sourceType);
}
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
return true;
else
return base.CanConvertTo(context, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var scContext = new SitecoreContext();
return scContext.CreateType(RequestedType, scContext.Database.GetItem(value.ToString()),true, false, new Dictionary<string, object>());
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
var config = Glass.Mapper.Context.Default.GetTypeConfiguration<SitecoreTypeConfiguration>(value.GetType(), true);
ID id =config.GetId(value);
return id.ToShortID().ToString().ToLowerInvariant();
}
My concern is that the ConvertFrom method does not get passed the type requested so we have to store this as property on the class to pass it from the CanConvertFrom method to the ConvertFrom method. This makes this class not thread safe.
Add this to the indexFieldStorageValueFormatter section of the sitecore config.
The problem here is that SearchResultItem is not actually an Item, but does have the GetItem() method to get the Sitecore item. What you need to do is the following:
List<MyMappedClass> results = context.GetQueryable<SearchResultItem>()
.Select(sri => sri.GetItem())
.Where(i => i != null)
.Select(i => i.GlassCast<MyMappedClass>())
.Where(c => c.field1.MyValue == "{GUID}").ToList();
I haven't worked with Glass specifically, but if you change your parent class to SearchResultItem, does it begin working? If so, that would indicate an issue with the SharedFieldClass parent class.

DbContext EntitySet null when entities are set to internal access

I want the db set to be internal in order to ensure external packages only have access to and program against the interface not the concrete class
e.g.
namespace Domain
{
public interface IProduct
{
string Description { get; }
int Id { get; }
decimal Price { get; }
}
}
//Separate Person.cs file for custom logic
namespace Domain
{
internal partial class Product :IProduct
{
}
}
internal partial class POS : DbContext
{
public POS()
: base("name=POS")
{
}
internal DbSet<Product> Products { get; set; }
}
//The other Person.cs file is generated by the .tt file
//_context.People is null which caused the dreaded null pointer exception :(
var people = _context.People.ToList();
As soon as I set the access to the Person class and People entity set to public via the Model Browser it works again, but I want to restrict the access to internal for package encapsulation.
It worked with Context in VS2010 EF but not with DbContext in VS2012.
Any help is much appreciated :}
P.S.
For now I have just edited the .tt file as below
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
Products = Set<Product>();
This generates the context class as below which instantiates the set, it would be nice to not have to add this to the .tt file for every entity set in the model.
internal partial class POS : DbContext
{
public POS()
: base("name=POS")
{
Products = Set<Product>();
}
I know this question is old but I just ran into this issue as well. According to a number of other StackOverflow posts, this is still the behavior of EntityFramework and the solution is still to explicitly Set<> the entity sets.
That said, instead of having to manually add each entity name to the .tt file, I created some code that will cause the TT file to automatically generate this code for each entity.
In the *.Context.tt file, you should spot the code for the constructor that looks something like this:
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoadingEnabled = false;
<#
}
#>
}
Modify this so it now looks like:
public <#=code.Escape(container)#>()
: base("name=<#=container.Name#>")
{
<#
if (!loader.IsLazyLoadingEnabled(container))
{
#>
this.Configuration.LazyLoadingEnabled = false;
<#
}
#>
<#
foreach (var entitySet in container.BaseEntitySets.OfType<EntitySet>())
{
#>
<#=codeStringGenerator.SetStatement(entitySet)#>
<#
}
#>
}
Further down in the file you should see a class definition for the CodeStringGenerator class, add a new method (I added mine directly under the DbSet method definition around line 307):
public string SetStatement(EntitySet entitySet)
{
return string.Format(
CultureInfo.InvariantCulture,
"{0} = Set<{1}>();",
_code.Escape(entitySet),
_typeMapper.GetTypeName(entitySet.ElementType));
}
When you save the template it should regenerate the DbContext class with the Set<> statements for each entity in your model. New entities that are added will re-trigger the template generation and those new entities will also be included in the constructor.

Is it possible to disable some page content, depending on PivotItem selection

I know that i can hide anything in codebehind, in selectionchanged event handler. But is it possible to, lets say, to have 2 PivotItems and one control outside of pivot, and hide that control, when 1st PivotItem is selected in xaml?
Worked, thanks to #Josh Earl, using the converter:
public class PivotIndexToVisibilityConverter : IValueConverter
{
public object Convert( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
{
int index = (int)value;
return index == 0 ? Visibility.Visible : Visibility.Collapsed;
}
public object ConvertBack( object value, Type targetType, object parameter, System.Globalization.CultureInfo culture )
{
Visibility visibility = ( Visibility )value;
return visibility == Visibility.Visible ? 0 : 1;
}
}
I don't think its possible to do this directly. You could get pretty close, though, if you databound your Visibility property to the PivotItem.SelectedItem property. You'd need to create a simple ValueConverter to translate your PivotItem index to a Visibility.Collapsed or Visibility.Visible as appropriate.
Here's a good intro to ValueConverter.

WP7 Uri as StaticResource?

I want to define URI in the resource files, and use them on the ApplicationBar. I done it as the first answer of the following question:
WP7 Image Uri as StaticResource
likes:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=System">
<sys:Uri x:Key="MenuButton1">/Images/button1.png</sys:Uri>
<sys:Uri x:Key="MenuButton2">/Images/button2.png</sys:Uri>
</ResourceDictionary>
But it doesn't work for me, the xaml file can't be parse.
And then I found another solution that is extending the StaticResourceExtension class, see the last answer of the following question:
Is it possible to supply a type converter for a static resource in WPF?
likes:
public class MyStaticResourceExtension : StaticResourceExtension
{
public IValueConverter Converter { get; set; }
public object ConverterParameter { get; set; }
public MyStaticResourceExtension()
{
}
public MyStaticResourceExtension(object resourceKey)
: base(resourceKey)
{
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
object value = base.ProvideValue(serviceProvider);
if (Converter != null)
{
Type targetType = typeof(object);
IProvideValueTarget target = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (target != null)
{
DependencyProperty dp = target.TargetProperty as DependencyProperty;
if (dp != null)
{
targetType = dp.PropertyType;
}
else
{
PropertyInfo pi = target.TargetProperty as PropertyInfo;
if (pi != null)
{
targetType = pi.PropertyType;
}
}
}
value = Converter.Convert(value, targetType, ConverterParameter, CultureInfo.CurrentCulture);
}
return value;
}
}
But I don't know whether it can be used on windows phone 7, and how to implement it, can someone give me some tips or example? or help me fix the first solution. thanks in advance.
You don't want to do this in XAML, since the ApplicationBar have no support for data-binding.
Instead, you should create the ApplicationBar with C#, which also offers you the ability of doing localization.
As for defining the URLs, I recommend you use a .NET Resource File, or define a static class with navigation URLs. The only reason for defining a URL as a resource in the first place, would be because you intend to re-use it, and as such, you're likely to also need to access it from C#, thus why a Resource File would be a optimal solution.
Here's an example of how to build a ApplicationBar in C#. It also allows you to add more features, like transparency toggling.
using the datatemplate may figure out your issue.

How do I remove format from Linq property?

I´m building a Windows Forms aplication using LINQ to SQL. I´m using the auto generated code from the
dbml file.
Visual studio generated this code for the CNPJ property from my table:
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_CNPJ", DbType="VarChar(20) NOT NULL", CanBeNull=false)]
public string CNPJ
{
get
{
return this._CNPJ;
}
set
{
if ((this._CNPJ != value))
{
this.OnCNPJChanging(value);
this.SendPropertyChanging();
this._CNPJ = value;
this.SendPropertyChanged("CNPJ");
this.OnCNPJChanged();
}
}
}
and what I wanted is this:
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_CNPJ", DbType="VarChar(20) NOT NULL", CanBeNull=false)]
public string CNPJ
{
get
{
return APPLY_FORMAT(this._CNPJ);//Changed here
}
set
{
if ((this._CNPJ != value))
{
this.OnCNPJChanging(value);
this.SendPropertyChanging();
this._CNPJ = REMOVE_FORMAT(value); /// Changed here
this.SendPropertyChanged("CNPJ");
this.OnCNPJChanged();
}
}
}
But I will lose this changes when the code is re-generated.
Question is: what is the right way to accomplish this behavior (inherit and override, capture change event, other ) ?
if you´re curious, CNPJ is the brazilin business identification number, provided by the government.
Rather than trying to change the existing property, create a new property.
public partial class YourClass
{
public string FORMATTED_CNPJ
{
get
{
return APPLY_FORMAT(this._CNPJ);
}
set
{
this.CNPJ = REMOVE_FORMAT(value);
}
}
}
If you don't want anyone to access the underlying CNPJ property you can set it to private in the designer (the access modifier combobox in the column properties window). You can even rename that property to _CNPJ, make it private, and then name your 'wrapper' property above CNPJ if you want to avoid any breaking changes.
LINQ to SQL creates the classes as partial classes. You can create another partial class in a different file but with the same class name and then you can change the behaviour.
public partial class YourClass
{
partial void OnCNPJChanged()
{
this._CNPJ = REMOVE_FORMAT(value);
}
}
See here for more information.

Resources