I am refactoring the code from sample:
24.129.21. Master Detail Binding
from C# / CSharp Tutorial » Windows Presentation Foundation » Binding)
And after excluding Skills class, with corresponding changes in
in MainWindow.xaml
<local:Team>
<local:Employee Name="Larry" Age="21">
<local:Employee.Skills>
<!-- local:Skills -->
<local:Skills>
in MainWindow1.xaml.cs:
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Windows;
namespace WpfApplication
{
public class Skill
{//I'd like to exclude class Skill having moved it into class Employee as nested one
public string Description { get; set; }
}
public class Employee
{
public string Name { get ; set; }
public int Age { get; set; }
public List<Skill> Skills { get; set; }
public Employee()
{
Skills=new List<Skill>();
}
/*class Skill
{
public string Description { get; set; }
} */
}
public class Team : ObservableCollection<Employee> { }
public class Company
{
public string CompanyName { get ; set; }
public Team Members { get ; set; }
}
public class Companies : ObservableCollection<Company> { }
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
How should I change Window1.XAML if to move:
Skill class into Employee class
in Window1.xaml.cs?
Related questions
based on the same code:
How to change a custom type to System type (string) in WPF XAML?
Update (answering 1st RV1987's comment):
Answers tp Creating an instance of a nested class in XAML tell that it is possible but unclear how to use:
answer by Ludovic tells that it is possible but contains comment that it is not clear how to use.
This is quite in line with my experience and this question
another answer by townsean is based on citation from msdn:
"Your custom class must not be a nested class. Nested classes and the "dot" in their general CLR usage syntax interfere with other WPF and/or XAML features such as attached properties."
But, it is in general, and for "your custom class" but in in my concrete code attached to this question there are dozens "dots" (like Employee.Skills) and it is not my custom class that is nested but my custom class has nested class inside.
Update2 (answering 2nd RV1987's comment-question):
Yes, I've just tried that + approach, which does not work, but:
XAML gives me errors even on perfectly working elements
I've not tried to use reflector myself or find any other workable approach or less ambiguous reference from Microsoft on it
Unfortunately, what you want to do is not possible in XAML (from MSDN):
Your custom class must not be a nested class. Nested classes and the "dot" in their general CLR usage syntax interfere with other WPF and/or XAML features such as attached properties.
Related
I've been getting my head into WPF the last few days, coming from a WinForms background, I just love the flexibility, especially in terms of binding.
However, I had a question after reading the following article on MVVM: http://blog.alner.net/archive/2010/02/09/mvvm-to-wrap-or-not-to-wrap.aspx
How to go about Models I have no control over, I cannot add interfaces to it, etcetera, I can only use them as-is?
Looking at the article, one option for me is to just directly expose the Model in my ViewModel, but would this be a good way to go about it? I could also use the wrapping option, but how do I bubble changes to those bubbles back to the ViewModel if they don't have a INotifyPropertyChanged interface? Are there any other options that allow TwoWay-binding to these Models?
EDIT:
Consider the following classes as models I cannot modify, what are my options:
[DataContract]
public class NPCTypeData
{
[DataMember]
public string Name;
[DataMember]
public List<NameAlias> Emotions;
}
[DataContract]
public class NameAlias
{
[DataMember]
public string Name;
[DataMember]
public string Alias;
}
I don't really care about the code required to turn these into bindable classes, I just want one or more examples on where to start with nested dependencies like this.
Do I copy all data to a Model that does have bindable properties and just leave these for serialization, do I wrap them, or what?
I agree with Henk, and would add that one option can be the "dynamic proxy class creation" which is what entity framework does. Basically: you have your POCO objects, and Entity framework can attach dynamically the necessary functionality to track the changes on model.
There's also an option to inherit from a class, and decorate the class with AOP attribute which generates all the necessary plumbing on the fly.
You can google for:
AOP INotifyPropertyChanged - http://www.postsharp.net/
Automatic INotifyPropertyChanged using Dynamic Proxy - http://jonas.follesoe.no/2009/12/23/automatic-inotifypropertychanged-using-dynamic-proxy/
When I had such problem, I basically used Henk solution, creating new classes and wrapping each property, using AutoMapper. Did it work & was it maintable? Yes, it worked, and it was maintable. Was it painful? Yes.
public class NPCTypeDataViewModel
{
public string Name {
get;
set;
}
public List<NameAliasViewModel> Emotions {
get;
set;
}
public NPCTypeDataViewModel(NPCTypeData data){
Name = data.Name;
Emotions = data.Emotions.Select(x => new NameAliasViewModel(x))
.ToList();
}
public NPCTypeData GetModel(){
var ntd = new NPCTypeData(){
Name = Name,
Emotions = Emotions.Select(emo => emo.GetModel())
.ToList()
};
return ntd;
}
}
public class NameAliasViewModel
{
public string Name {
get;
set;
}
public string Alias {
get;
set;
}
public NameAliasViewModel(NameAlias alias){
Name = alias.Name;
Alias = alias.Alias;
}
public NameAlias GetModel(){
return new NameAlias(){
Name = Name,
Alias = Alias
};
}
}
I've got 2 classes with many different properties and one similar property:
public class A
{
// Lots of specific properties
[Display(Name="Dun and bradstreet number")]
public string DunAndBradstreetNumber {get;set;}
}
public class B
{
// Lots of specific properties
[Display(Name="Dun and bradstreet number")]
public string DunAndBradstreetNumber {get;set;}
}
I realise I have an abundance of choice and I just want to make sure i'm choosing the most semantically correct and popular choice.
1:-----------
Should I declare another class:
public class DunAndBradstreetNumber
{
[Display(Name="Dun and bradstreet number")]
public string DunAndBradstreetNumber {get;set;}
}
and then make class A and B have pointers inside them eg.?
public class A
{
public DunAndBradstreetNumber DunAndBradstreetNumber { get; set; }
}
or
2:-----------
inherit from the DunAndBradstreetNumber?
public class A : DunAndBradstreetNumber
{
//...
}
3:-----------
declare a global function and put that in the get method of each DunAndBradstreetNumber?
public class A
{
public string DunAndBradstreetNumber {
get
{
// Run some function that I may need help on to apply property validation via attributes to
}
set;
}
}
Any more better choices?
My class A and B are domain models using entityframework if that helps at all.
The problem i'm trying to solve is to not have to declare the validation and display attributes twice in different models.
P.S - your opinion is fine... I just want to know the eventualities of the choice I have to make here (albeit its relative insignificance).
I have been looking into DataAnnotations and creating my own DataAnnotations for future use - mainly in MVC4 (which is fairly easy it's safe to say). I want to verify how useful, effective and easy to use they will be if I use the same Model classes in a WPF project.
public class Customer
{
public int Id { get; set; }
[Required()]
public string Name { get; set; }
}
public class ViewModelBase : IDataErrorInfo, INotifyPropertyChanged
{
//... (INotifyPropertyChanged)
public string Error
{
get
{
return string.Empty;
}
}
public string this[string columnName]
{
get
{
//According to tutorials, something here
return string.Empty;
}
}
}
So if I were to move on to creating a CustomerViewModel which inherits from the base class, would I have to present a subset view of the model properties like:
public class CustomerViewModel : ViewModelBase
{
[Required]
public string Name { get; set; }
}
Meaning I have to implement the annotations again, or is it possible to just use the model and somehow reflect model validation back to the front end using WPF's MAGICAL binding?
I have been looking at numerous articles, but none of which seem to be neat or very consice - such as:
http://blog.paulbetts.org/index.php/2010/04/27/wpf-data-validation-using-dataannotations/
Why would you put another Name property in your viemodel?
If you have a Customer property in your viewmodel, you can access it in you xaml like:
{Binding Customer.Name}
This will automatically take your dataanotations from your model class.
Edit: For a good example see: http://www.codeproject.com/Articles/98681/Validating-User-Input-WPF-MVVM
I have an Entity Framework Model created using Entity Framework Code First that is using Table Per Hierarchy inheritance where the structure looks a little like this:
public abstract class BaseState
{
public int Id { get; set; }
public string StateName { get; set; }
// etcetera
}
public class CreatedState : BaseState
{
public User Owner { get; set; }
}
public class UpdatedState : BaseState
{
public User Owner { get; set; }
}
Now what that creates is in my BaseStates table I have Owner_Id and Owner_Id1 stored. But given that no class will ever be both a CreatedState and an UpdatedState it seems as though it would be logical to use a single Owner_Id for both. Which would also make it easier to follow the database.
My basic question is: Is this possible with Code First EF4?
I have tried to map the columns:
public class CreatedState : BaseState
{
[Column("OwnerId")]
public User Owner { get; set; }
}
public class UpdatedState : BaseState
{
[Column("OwnerId")]
public User Owner { get; set; }
}
That appeared to have no effect.
Then I tried creating a shared parent class, which is probably more correct OO anyway:
public abstract class OwnedState : BaseState
{
public User Owner { get; set; }
}
public class CreatedState : OwnedState
{
}
public class UpdatedState : OwnedState
{
}
Again, no dice. Or, more worryingly, this appears to work in some cases and not in others ( obviously my real configuration is slightly more complex ) when I can see precisely no difference between the classes where it does work.
Edit for more detail on what fails:
I have two fields that behave in the way I have described above, we might call the associated classes OwnedState and ActivityState, both of which I have created as an abstract class in the way shown in my last example. OwnedState has two classes that derive from it, ActivityState has three. In the database I have ActivityState_Id but also OwnedState_Id and OwnedState_Id1.
I can see no difference at all between the OwnedState and ActivityState classes aside from the type that they reference ( both other entities ) and yet in the database it appears as though EF has somehow interpreted them differently- I don't understand the EF internals well enough to know how it makes that decision.
If you want to have one Owner_ID to have both CreatedState and UpdatedState to refer to, then the User Owner should be placed in the BaseState.
I don't know what you are trying to do with this, but logically, you wouldn't be having CreatedState and UpdatedState as classes, but more of values of State property (or column in database) to save the state (Created or Updated). But, again, maybe you are trying something else with this.. I guess.
I have an employee class generated by Entity Framework (EF).
public partial class employee
{
private string name;
public string Name
{
get{return name;}
set{ name = value;}
}
}
Now I want to put a required attribute in the name property to use in for MVC3 validation in another employee partial class which is written by me in order to extend the one which is generated by EF so that I don't have to rewrite my code if I refresh the model generated by EF.
My written partial class is in the same assembly and name space.
public partial class employee
{
// What should I write here to add required attribute in the Name property?
}
It is actually possible only through buddy class but it is not recommended way. You should keep your validation in custom view model because often you need different validations for different views but your entity can keep only single set of validation attributes.
Example of buddy class:
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(EmployeeMetadata))]
public partial class Employee
{
private class EmployeeMetadata
{
[Required]
public object Name; // Type doesn't matter, it is just a marker
}
}
You can't, as far as I'm aware - it's just not feasible.
You should possibly look to see whether MVC3 has any way of adding attributes elsewhere (e.g. to the type) which relate to another property.
Alternatively, you could add a proxying property:
[ValidationAttributesHere]
public string ValidatedName
{
get { return Name; }
set { Name = value; }
}
Another way to do this is:
private class EmployeeMetadata
{
//the type HAS to match what your have in your Employee class
[Required]
public string Name { get; set; }
}
public partial class Employee : EmployeeMetadata
{
}
At least this worked with Linq to SQL. However I had trouble accessing the attributes through GetCustomAttributes (even using System.Attribute.GetCustomAttributes didn't seem to help). Nonetheless MVC did respect those attributes. Additionally this will not work with inheriting from interfaces. Passing attributes from interface will only work using MetadataType class attribute (see answer by Ladislav Mrnka).