I have a property that is of type DateTime that I would like to bind to a viewmodel. When I bind the property I am getting and error stating that the binding type must be a reference type. How can I bind this property to my viewmodel and be notified of it's changes?
Specifically, the code that is causing the compiler error looks like this:
set.Bind (StartDate).To (vm => vm.StartDate);
Here is the property on the view.
public static DateTime StartDate { get; set; }
The general pattern for Fluent binding is:
set.Bind (target).For(v => v.TargetProperty).To (vm => vm.SourceProperty);
This binds the TargetProperty of target to the SourceProperty of the source DataContext (normally the ViewModel).
When For is omitted, then MvvmCross looks up a default property.
In your code, you are trying to bind the default property of the current StartDate to the ViewModel's StartDate. I suspect what you wanted instead was:
set.Bind(this).For(v => v.StartDate).To(vm => vm.StartDate);
For more on fluent data-binding syntax, please see the wiki http://github.com/mvvmcross/mvvmcross/wiki
Related
I am using the Interface IOptions in Core 2.0:
public interface IOptions<out TOptions> where TOptions : class, new()
And in my Startup.cs I can wire it up,
// Example #1: Basic options
// Register the ConfigurationBuilder instance which MyOptions binds against.
services.Configure<MyOptions>(Configuration);
private readonly MyOptions _options;
_options = optionsAccessor.Value;
What I want to know is how does the Framework know what Value is supposed to be? Where is "Value" assigned? It's not the same as value in a property, it appears. Here Value is a whole class reference.
For checking the depth implementation of Options, you could download Options, and debug the project.
how does the Framework know what Value is supposed to be?
While you configure the Options, you have passed the type by services.Configure<MyOptions>(Configuration) , the MyOptions will passed into generic type TOptions.
It's not the same as value in a property, it appears. Here Value is a whole class reference.
Tha Value is TOptions type which is returned by OptionsManager.
public TOptions Value
{
get
{
return Get(Options.DefaultName);
}
}
Where is "Value" assigned?
Value will be configured by ConfigureNamedOptions and created by OptionsFactory, then you could access it by OptionsManager.
I am using INotifyPropertyChanged so that my domain objects in a class library can notify progress of their execution methods. This is not related to WPF or DataBinding situations.
I have read the documentation about PropertyChanged event and the PropertyChangedEventArgs has only a PropertyName property:
A PropertyChanged event is raised when a property is changed on a component. A PropertyChangedEventArgs object specifies the NAME of the property that changed.
PropertyChangedEventArgs provides the PropertyName property to get the NAME of the property that changed.
Problem is: I need to get the VALUE of the changed property, not its name, so I ask:
Is there a way to get the value of a property in PropertyChanged event args?
(because if not, I think I'll have to create myself a ReportProgress event, similar to BackgroundWorker class, is that right?)
Thanks for reading.
You can still get the value by handling PropertyChanged. Just use the name to go back and get the value.
someObject.PropertyChanged += (sender, e) => {
var value = sender.GetType()
.GetProperty(e.PropertyName)
.GetValue(sender, null);
// do something with value?
};
Check out Type.GetProperty() and PropertyInfo.GetValue().
I am calling a generic method with two different classes as below:
FillDataPointsInOrder<Metrics>(dataPoints.Where(O => O.SortOrder != null).OrderBy(O => O.SortOrder));
FillDataPointsInOrder<Metric>(angieStatsCmp.GetDataColumns());
private void FillDataPointsInOrder<T>(IEnumerable<T> dataPoints)
{
foreach (T dpoint in dataPoints)
{
if (!dpoint.IsPhone)
FillDrp(this.EmailDrp, dpoint.Name, dpoint.MetricId.ToString(), dpoint.VName);
if (dpoint.IsPhone && this.IsPhoneShop)
FillDrp(this.PhoneDrp, dpoint.Name, dpoint.MetricId.ToString(), dpoint.VName);
}
}
in "FillDataPointsInOrder" method I am getting compile errors :
'T' does not contain a definition for 'IsPhone' and no extension method 'IsPhone' accepting a first argument of type 'T' could be found (are you missing a using directive or an assembly reference?)
Same errors for Name , MetricId and VName properties.
Not sure why T is not able to access properties of Metrics and Metric.
If I remove the code from generic method and write it directly in foreach over dataPoints it is working fine.
Can somebody advise what is wrong here?
FillDataPointsInOrder only knows it will be called with a T. T could actually be string, int or anything.
If you want to call properties on T, you will have to use a where constraint.
But in this case it looks like your method does not even need to be generic.
If both Metric and Metrics share a base class or an interface that has the properties you need:
interface IMetric {
bool IsPhone {get; }
}
you could just have:
private void FillDataPointsInOrder(IEnumerable<IMetric> dataPoints)
Note that IEnumerable is covariant, so if Metric is a IMetric, IENumerable<Metric> is a IEnumerable<IMetric>
You need to at least tell the compiler something about T if you want to do that. Do you have an interface that has members like IsPhone, Name, MetricId, etc. that your classes implement?
If so you can add a 'where' constraint to your class definition:
public class Something<T> where T : ISomethingElse
...where ISomethingElse is the interface that implements IsPhone.
I want to customise the way AutoMapper converts my types without losing the features already implemented by AutoMapper.
I could create a custom ITypeConverter instance but I can't see how to invoke the default behaviour.
Mapper.CreateMap<MyDomainObject, MyDto>
.ConvertUsing<MyTypeConverter>();
...
public class MyTypeConverter : TypeConverter<MyDomainObject, MyDto>
{
public MyDto ConvertCore(MyDomainObject source)
{
var result = // Do the default mapping.
// do my custom logic
return result
}
}
If I try to call var result = Mapper.Map<MyDto>(source) it gets into an infinite loop. I effectively want AutoMapper to do everything it normally would assuming there was no TypeConverter defined.
Any help greatly appreciated.
If you only want to customise some values on the destination object, then you're better off with a Custom Value Resolver - TypeConverters are designed to handle the whole conversion.
The doc page listed above will have enough to get you started: when you have implemented the CustomResolver you apply it like this, and AutoMapper will do the default mapping for the other properties:
Mapper.CreateMap<MyDomainObject, MyDto>()
.ForMember(dest => dest.TargetProperty,
opt => opt.ResolveUsing<CustomResolver>());
I'm trying to re-use some of the model configurations on several entities that implements a interface.
Check this code:
public static void ConfigureAsAuditable<T>(this EntityTypeConfiguration<T> thisRef)
where T : class, IAuditable
{
thisRef.Property(x => x.CreatedOn)
.HasColumnName("utctimestamp")
.IsRequired();
thisRef.Property(x => x.LastUpdate)
.HasColumnName("utclastchanged")
.IsRequired();
} // ConfigureAsAuditable
as you can see I'm trying to call the extension method "ConfigureAsAuditable" on my onmodelcreating method like this:
EntityTypeConfiguration<Account> conf = null;
conf = modelBuilder.Entity<Account>();
conf.ToTable("dbo.taccount");
conf.ConfigureAsAuditable();
When debugging i get this exception:
The property 'CreatedOn' is not a declared property on type
'Account'. Verify that the property has not been explicitly excluded
from the model by using the Ignore method or NotMappedAttribute data
annotation. Make sure that it is a valid primitive property.
Thanks in advance :)
PD:
I'm using EF 5-rc, VS 2011 and .NET Framework 4.5
I think a better approach would be to implement your own derived version of EntityTypeConfiguration. For example:
public class MyAuditableConfigurationEntityType<T> : EntityTypeConfiguration<T>
where T : class, IAuditable{
public bool IsAuditable{get;set;}
}
Then, when building your model, use that new type:
var accountConfiguration = new MyAuditableConfigurationEntityType<Account>();
accountConfiguration.IsAuditable = true; // or whatever you need to set
accountConfiguration.(HasKey/Ignore/ToTable/Whatever)
modelBuilder.Configurations.Add(accountConfiguration);