Validation of a combobox in Silverlight 4 - silverlight

I'm trying to understand how validation works for a combo box when its ItemsSource is bound to a ObserableCollection of complex types. I am using RIA as the serivce to connect the client tier to the middle tier. Also not sure if this makes a difference the combobox control is inside a dataform. I have done alot of reading on this and found this article to be the most useful: http://www.run80.net/?p=93
So firstly my entity: I have a field decorated like so:
[Required]
public virtual long FrequencyId { get; set; }
[Include]
[Association("TreatmentFrequencyToTreatmentRecordAssociation", "FrequencyId", "Id", IsForeignKey = true)]
public virtual TreatmentFrequency Frequency
{
get
{
return this.frequency;
}
set
{
this.frequency = value;
if (value != null)
{
this.FrequencyId = value.Id;
}
}
}
Now I belive that I cannot set the [Required] annotation on an association but instead on the foreign key id (what the above article says).
The actual Treatment Frequency class looks like this:
public class TreatmentFrequency
{
[Key]
public virtual long Id { get; set; }
[Required]
[StringLength(10)]
public virtual string Code { get; set; }
[Required]
[StringLength(40)]
public virtual string Name { get; set; }
public override bool Equals(object obj)
{
obj = obj as TreatmentFrequency;
if (obj == null)
{
return false;
}
return this.Id == ((TreatmentFrequency)obj).Id;
}
public override int GetHashCode()
{
return this.Name.GetHashCode();
}
}
I have overriden the Equals and GetHashCode method becuase in another article it said that when in a collection you need to override the equals to match on the key otherwise when you use SelectedItem although all the values would be the same between the item in the collection and the selecteditem they would be two different instances and thus not match with the default implementation of Equals.
Now my xaml looks like this:
<df:DataField Label="Frequency">
<ComboBox SelectedItem="{Binding Path=CurrentItem.Frequency, Mode=TwoWay}" ItemsSource="{Binding Path=Frequencies}" DisplayMemberPath="Name" SelectedValue="{Binding Path=CurrentItem.FrequencyId, Mode=TwoWay}" SelectedValuePath="Id"/>
</df:DataField>
To be honest the above doesn't make much sense to me, I could remove SelectedValue and SelectedValuePath and the form would still work as expected (without validation) I thought that Selected Value would point to the complex type E.g. CurrentItem.Frequency and then the SelectedValuePath would be the underlying "Name" property. However I also understand what the author is trying to do in that the [Required] tag isn't on the association but the foreign key id E.g. CurrentItem.FrequencyId, so it must have to go somewhere.
Now a final compelexity is that this form is part of a wizard so I am not able to validate the entire object, instead I manually have to validate certain field which are only being populated in this particular wizard step. To do this I created the method:
public void ValidateProperty(object value, string propertyName)
{
var results = new List<ValidationResult>();
Validator.TryValidateProperty(value, new ValidationContext(this.TreatmentRecord, null, null) { MemberName = propertyName }, results);
foreach (var error in results)
{
this.TreatmentRecord.ValidationErrors.Add(error);
}
}
In my view model I have a method IsValid which is called before the wizard is allowed to navigate to the next step and then I call the above method like so:
public bool IsValid
{
get
{
this.treatmentRecordWizardContext.ValidateProperty(this.treatmentRecordWizardContext.TreatmentRecord.Frequency, "Frequency");
this.treatmentRecordWizardContext.ValidateProperty(this.treatmentRecordWizardContext.TreatmentRecord.FrequencyId, "FrequencyId");
this.OnPropertyChanged(() => this.CurrentItem);
if (this.treatmentRecordWizardContext.TreatmentRecord.ValidationErrors.Count == 0)
{
return true;
}
return false;
}
}
With all of the above code the validation is completly ignored when the combobox is left empty. I have not templated the combobox itself so I am really at a loss as to why its not working and really which part of the solution is at fault, is it the bindings or is it the entitys in the RIA not defined correctly!
Hope someone can help I've spent far too long trying to get this to work, I assume this must be done reqularly by other developers so I'm hoping its a simple fix.

This was actually a simple problem in th end, I assumed that the [Required] annotation would check that the association was present and not null. It seems that all it actually does is check that in this case that FrequencyId is not null. And there was the problem in that I was using a long and not a nullable long (long?). Once I made the change to make them nullable the validation started working as expected even with the bindings which made no sense to me. If anyone could explain them that would be great!
Phil

Related

Fill a combobox in WPF with a list of web services

I have a control like this:
<ComboBox x:Name="ComboTipo"
Height="23"
SelectionChanged="ComboTipo_SelectionChanged"
Width="450"
Canvas.Left="609"
Canvas.Top="26" />
And my code is:
ComboTipo.DisplayMemberPath = "Descripcion";
ComboTipo.SelectedValuePath = "IdTipoPersona";
ComboTipo.ItemsSource = myWebServices.dameTipos();
My web services returns a list for this object, this class is created in automatic when i add the reference to the web services:
public partial class TipoPersona {
private short idTipoPersonaField;
private string descripcionField;
/// <comentarios/>
public short IdTipoPersona {
get {
return this.idTipoPersonaField;
}
set {
this.idTipoPersonaField = value;
}
}
/// <comentarios/>
public string Descripcion {
get {
return this.descripcionField;
}
set {
this.descripcionField = value;
}
}
}
But the problem is:
The combobox displays the data types for each element of the list, and i want display the Descripcion.
Can you help me plis! Thanks
What does IdTipoPersona look like? Is it a class you created? If so, you may need to reference the property that you want displayed. It would look something like this:
ComboTipoPersona.SelectedValuePath = "IdTipoPersona.Text";
Where Text would be replaced by the property. It is really hard to judge otherwise what is going on with knowing a little more about the object structure that myWebServices.dameTipos() returns.
EDIT
Ok I was able to simulate your problem and simulate a solution as well.
Your issue is in the Tipos class. There are a couple of things necessary when binding to a combobox with a custom class.
First off, you will want to add accessors and mutators (getters and setters) to IdTippoPersona and Descripcion.
You should add a constructor that assigns to those properties with parameters.
It is usually a good idea to add a default constructor.
The finished code will look like this:
public class Tipos
{
public int IdTipoPersona { get; set; }
public string Descripcion { get; set; }
public Tipos(int id, string descripcion)
{
IdTipoPersona = id;
Descripcion = descripcion;
}
}
I found the asnwer if someone needs it.
We need create a class intermediate class but we were working with entity framework, for this way, we need add the intermediate class like complex type in my model (entity framework).
And also we need override this class.
And it works so well.
Thanks for all #Goody

WPF / MVVM / EF - How to bind to an entity's related entities?

I have a detail view corresponding to a user entity. Each user entity has one or more comment entities, which is represented on the detail view as a grid.
So following EF convention, the user model has a UserComments member to represent the relation:
public partial class User
{
public int UserID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public virtual ICollection<UserComments> UserComments { get; set; }
//....
}
When it came time to create the user comments grid in the user detail view, I realized that the grid does not properly bind to an ICollection (couldn't add new rows to the grid). After some digging, I found that I needed to use an ObservervableColletion. Ok, so I converted my ICollection into an ObserverableCollection....
public class UserDetailViewModel
{
public virtual User UserData { get; set; }
private ObservableCollection<UserComments> _UserComments;
public ObservableCollection<UserComment> UserComments {
get { return _UserComments; }
}
public void Load(int UserID)
{
this.UserData = UserRepo.Find(UserID);
this._UserComments = new ObservableCollection<UserComment>(UserData.UserComments);
}
}
Cool. I can add rows to the grid now. But...
At this point, I've realized I've lost EF change tracking by converting User.UserComments to an ObservableCollection and have no easy way of getting the modifed/new comments back into EF.
So have I approached this all wrong? Is there a better way of updating the related data?
In order for EF to track collection changes, you need to be adding and removing from the collection in the model itself.
this._UserComments = new ObservableCollection<UserComment>(UserData.UserComments);
In the line above, you're creating a collection by copying elements, so when items are added to or removed from UserDetailViewModel.UserComments, those items aren't actually being added to or removed from User.UserComments.
Some options to fix this include:
Changing User.UserComments itself to an ObservableCollection and exposing that in the view model. For example:
public class UserDetailViewModel
{
public virtual User UserData { get; set; }
public ObservableCollection<UserComment> UserComments
{
get { return UserData.UserComments; }
}
// other stuff...
}
Handling add/remove events for UserDetailViewModel.UserComments and modifying the User.UserComments collection there.
This might be helpful as well:
https://msdn.microsoft.com/en-us/data/jj574514.aspx

What kind of compiler magic do we need more?

I develop lot view models which are:
1) All have to implement INotifyPropertyChanged to be bindable to UI.
2) Property setters have to raise PropertyChanged on change.
3) PropertyChanged event has to provide proper property name.
If you (like me) tied of writing something like this:
public string Name
{
get
{
return _name;
}
set
{
if (_name != value)
{
_name = value;
RaisePropertyChanged("Name");
}
}
}
Then refactor this method like this and sometimes forget to update property name literal:
string _fundName;
public string FundName
{
get
{
return _fundName;
}
set
{
if (_fundName != value)
{
_fundName = value;
RaisePropertyChanged("Name");
}
}
}
And then spend a day to debug why your UI is not refreshing and databinding doesn't work properly.
Then all we need is some kind of magic.
What if I just need to write this:
[Magic] // implicit transformation
public string FundName { get; set; }
or if I have many properties:
[Magic]
public class MyViewModel
{
public string FundName { get; set; }
public string FundType { get; set; }
[NoMagic] // suppress transformation
public int InternalId { get; set; }
}
So I have just developed a MSBuild task to do this magic after the build (http://kindofmagic.codeplex.com).
The question is, what kind of magical postprocessing would you like more?
Does automatic implementation of INotifyPropertyChanging makes sense?
Try this
http://code.google.com/p/notifypropertyweaver/
No attributes required
No references required
No base class required
Here is my blog article about it
http://codesimonsays.blogspot.com/2010/11/attempting-to-solve-inotifypropertychan.html
It supports the attributes you request
NotifyPropertyAttribute (notify for a property)
NotifyForAllAttribute (notify for all properties on a type)
NotifyIgnoreAttribute (do not notify for a property or type)
AlsoNotifyFor (Allows the injection of notify code that points to a different property)
Although these are option and designed for fine tuning. Most injection is done by convention through analyzing the existing IL.
If we're going to have fancy code generation, I think I would prefer a way to generate DependancyProperties more easily. The snippit I use is certainly helpful, but I'm not a fan how jumbled the code looks when you have on-changed and coerce callbacks, and metadata options. Maybe I'll try and mock up a sample after work.
Edit: Well, here's one concept. It would look a lot more clever if you pass anonymous methods to attributes, but it's still a step up.
Before:
[DpDefault("The Void")]
[DpCoerce(new CoerceValueCallback(MainWindow.CoerceAddress))]
[DpChanged(new PropertyChangedCallback(MainWindow.ChangeAddress1))]
[DpChanged(new PropertyChangedCallback(MainWindow.ChangeAddress2))]
[DpOptions(FrameworkPropertyMetadataOptions.Inherits)]
public string Address {
get { return Dp.Get<string>(); }
set {
if (Dp.Get<string>() != value) {
Dp.Set(value);
PostOffice.SendMailToTheBoss("I moved!");
}
}
}
After:
public string Address {
get { return (string)GetValue(AddressProperty); }
set {
if ((string)GetValue(AddressProperty) != value) {
SetValue(AddressProperty, value);
PostOffice.SendMailToTheBoss("I moved!");
}
}
}
public static readonly DependencyProperty AddressProperty =
DependencyProperty.Register("Address", typeof(string), typeof(MainWindow),
new FrameworkPropertyMetadata((string)"The Void",
FrameworkPropertyMetadataOptions.Inherits,
new PropertyChangedCallback(MainWindow.ChangeAddress1)
+ new PropertyChangedCallback(MainWindow.ChangeAddress2),
new CoerceValueCallback(MainWindow.CoerceAddress)));
Typically, only the 'DpDefault' attribute would be used, but even if it doesn't make the code shorter, it certainly makes it clearer. Here would be a more typical example:
Before:
[DpDefault("The Void")]
public string Address { get; set; }
After:
public string Address {
get { return (string)GetValue(AddressProperty); }
set { SetValue(AddressProperty, value); }
}
public static readonly DependencyProperty AddressProperty =
DependencyProperty.Register("Address", typeof(string), typeof(MainWindow),
new UIPropertyMetadata((string)"The Void"));
"Magic" is almost always a terrible name for method or property or variable in any language. You should rename the attribute to something more descriptive. Imagine you are just a random internet pedestrian and stumble on a piece code with attribute "Magic", what does it tell you about the code? Exactly nothing :)
I will try your code anyways, it has potential to be quite a timesaver. This should definitely be a part of .NET.
Something that might make your life a little easier is this... (Ive picked it up from Caliburn Micro).
public virtual void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property) {
NotifyOfPropertyChange(property.GetMemberInfo().Name);
}
This enables you to do the following..
NotifyOfProperyChange(() =>
this.PropertyName);
This will highlight any issues with the code at design time, rather than run time.
Caliburn Micro is an awesome little framework that you should take a look at, it removes so much of the wiring up involved with MVVM and Silverlight / WPF!
This can already be done using a AOP (Aspect Oriented Programming) tool like PostSharp : http://www.richard-banks.org/2009/02/aspect-oriented-programming.html (using v1.x)
http://www.sharpcrafters.com/solutions/ui#data-binding (using v2.0)
I used PostSharp to implement INPC in few projects and it worked out pretty well, the code is much more cleaner and maintainable (it adds a few seconds to compile time)

MVVM - RaisePropertyChanged turning code into a mess

New to MVVM so please excuse my ignorance.
I THINK i'm using it right but I find my ViewModel has too many of these:
RaisePropertyChanged("SomeProperty")
Every time I set a property I have to raise that damned property changed.
I miss the days where I could just go:
public int SomeInteger { get; private set;}
These days I have to stick the "RaisePropertyChanged" in everywhere or my UI does not reflect the changes :(
Am I doing it wrong or are other people getting annoyed with the excessive number of magic strings and old school property setters?
Should I be using dependency properties instead? (I doubt that would help the code bloat anyway)
Despite these problems I still think MVVM is the way to go so I guess that's something.
Take a look at this What is the best or most interesting use of Extension Methods you've seen?.
It describes an extension method and a helper method that my Model and ViewModel classes use to enable the following strongly typed (no magic string) properties.
private string _name;
public string Name
{
get { return _name; }
set { this.NotifySetProperty(ref _name, value, () => this.Name); }
}
This is about as simple as I think it can get. Hope it helps.
You could use PostSharp's NotifyPropertyChanged attribute. Then all you have to do is to put an attribute on the class and that's it. E.g.:
[NotifyPropertyChanged]
public class MyClass
{
public string MyProperty { get; set; }
}
It helps to look at things from a different perspective: those are not complicated .NET properties, but simplified dependency properties.
Bindable properties of a view model in WPF are not identical to .NET properties, instead it is a kind of key-value store. If you want light-weight alternative to DependencyObject, you have an ability to implement this key-value store just buy calling certain function in setters - not bad, actually. Far from ideal too, of course, but your point of view is certainly unfair.
It does not get you back to the clean code, but I use a simple extension method to get the property name to avoid problems with magic strings. It also maintains the readability of the code, i.e. it is explicit what is happening.
The extension method is simply as follows:
public static string GetPropertyName(this MethodBase methodBase)
{
return methodBase.Name.Substring(4);
}
With this it means that you property sets are resilient against name changes and look like the following:
private string _name;
public string Name
{
get { return _name; }
set
{
name = value;
RaisePropertyChanged(MethodBase.GetCurrentMethod().GetPropertyName());
}
}
I've written more about this extension method here and I've published a matching code snippet here.
This will help:
"Kind Of Magic"
Effortless INotifyPropertyChanged
[http://visualstudiogallery.msdn.microsoft.com/d5cd6aa1-57a5-4aaa-a2be-969c6db7f88a][1]
as an example for adding it to one property:
[Magic]
public string Name { get { return _name; } set { _name = value; } }
string _name;
Another example for adding it to all the class properties:
[Magic]
public class MyViewModel: INotifyPropertyChanged
{
public string Name { get; set; }
public string LastName { get; set; }
.....
}

Creating a Dynamic Linq filter over List<T>

Ok, I asked this question before, but deleted it as the way I went about describing my problem was wrong.
Firstly, let me state that Im creating a .NET3.5 Winforms app using C# and Plinqo (Professional Linq to Objects) as my ORM. Here's my situation: I have a DataGridview that is populated from a SortableBindingList<T> - in my case, formed from a List<Task> which is simply represented as follows:
public class Task {
public long TaskID { get; set; }
public string TaskDescription { get; set; }
public enumPriority TaskPriority { get; set; }
public DateTime DueDate { get; set; }
public double PercentageComplete { get; set; }
}
Now, I want to provide a Dialog to my user to allow him/her to Filter this list. I envision passing in a list of property names and associated DataType into the Dialog that I can use to populate a ComboBox. So the user will choose which property they want to query from the comboBox and based on the selection the appropriate comparers and UI control will be made available for the user to enter in thier criteria. Lastly, it will contain an AND/OR togglebutton at the end which the user can use to add additional criterion. Each criterion will be an object of type FilterItem as shown below:
public class FilterItem {
public string MappedPropertyName { get; set; }
public enumComparer Comparer { get; set; }
public object FilterValue { get; set; }
public enumOpertor Operator { get; set; }
}
After the user constructs his/her query, I intend to pass this as a List<FilterItem> back to my calling form, which can then iterate thru the list and allow me to filter the original List<Task>.
This is all fine, and something that I can put together with ease. But I want to make sure that the ACTUAL filter mechanism I go with is as strongly-typed as possible, and not using bulit up strings like in the Dynamic Query Library. (I used to do something similar previously with ADO.NET, DataViews and dynamically constructing a RowFilter string)
I've read up on Joseph Albahari's PredicatBuilder and an article on tomasp.net, but I seem heavily confused with it and expression trees in general.
I sincerely seek your assistance in helping me better understand these concepts, and how to go about using it up so that my intended architecture can work with it.
Much appreciation!
Additionally, I know I can do something like:
private SortableBindingList<Task> GetSortedTaskList()
{
List<Task> list = new List<Task>();
var query = DataUtil.GetUserTasks(xSys.Current.UserID);
if (/*description condition met*/)
{
query = query.Where(x => x.TaskDescription.Contains(FilterDesc));
}
if (/*due date condition met*/)
{
query = query.Where(x => x.DueDate >= FilterDate);
}
if (/*priority condition met*/)
{
query = query.Where(x => x.TaskPriority == FilterPriority);
}
...
list = query.ToList();
return new SortableBindingList<ArcTask>(list);
}
but this does not seem very scalable and 'dynamic'.

Resources