This is the first time I'm working with List
Here is my code (Removed all the unwanted lines for simplification)
Class1
public class RInfo
{
public int RCode { get; set; }
public int ACode { get; set; }
public int DCode { get; set; }
public string RNo { get; set; }
//public DateTime EDate { get; set; }
//public DateTime? VDate { get; set; }
}
Class 2
public class DInfo
{
public int DCode { get; set; }
public string DName { get; set; }
public bool DCExpires { get; set; }
}
Class that I will get after joining above two classes
public class RInfo_Details
{
public int RCode { get; set; }
public int ACode { get; set; }
public int DCode { get; set; }
public string DCName { get; set; }
public string DName { get; set; }
public string RNo { get; set; }
//public DateTime EDate { get; set; }
//public DateTime? VDate { get; set; }
}
Here is my class this is used to retrive data and for binding in XAML
public class AppData : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
private AppData() { }
private static AppData instance = null;
public static AppData Instance
{
get
{
if (instance == null) instance = new AppData();
return instance;
}
}
AInfo _SelAInfo;
public AInfo SelAInfo
{
get => _SelAInfo; set
{
_SelAInfo = value; RaisePropertyChanged(nameof(SelAInfo));
RaisePropertyChanged(nameof(RInfo_List));
RaisePropertyChanged(nameof(RInfoDetailedList));
}
}
List<DInfo> _DInfo;
public List<DInfo> DInfo { get => _DInfo; set { _DInfo = value; RaisePropertyChanged(nameof(DInfo)); } }
List<RInfo> _RInfo;
public List<RInfo> RInfo { get => _RInfo; set { _RInfo = value; RaisePropertyChanged(nameof(RInfo)); RaisePropertyChanged(nameof(RInfoDetailedList)); } }
public IEnumerable<RInfo_Details> RInfoDetailedList
{
get
{
IEnumerable<RInfo_Details> newlist = (from r in RInfo
join d in DInfo
on r.DCode equals d.DCode
select new
{
r.RCode,
r.ACode,
r.DCode,
d.DName,
d.DCExpires,
r.RNo,
}).ToList() as IEnumerable<RInfo_Details>;
return newlist as IEnumerable<RInfo_Details>;
}
}
public void iniTestData()
{
this.DInfo = new List<DInfo>()
{
new DInfo{DCode=1, DCExpires=false, DName="PAN" },
new DInfo{DCode=2, DCExpires=true, DName="FSSAI" },
new DInfo{DCode=3, DCExpires=false, DName="AANDAHR" }
};
this.RInfo = new List<RInfo>()
{
new RInfo{RCode=1, ACode=1, DCode=1, RNo="PAN NO ACode 1" },
new RInfo{RCode=2, ACode=2, DCode=1, RNo="PAN NO ACode 2" },
new RInfo{RCode=3, ACode=5, DCode=3, RNo="AADHAR ACode 5" },
new RInfo{RCode=4, ACode=4, DCode=1, RNo="PAN NO ACode 4" }
};
}
}
Here is code in XAML that is binding AppData.RInfoDetailedList
<ListView ItemsSource="{Binding Source={x:Static local:AppData.Instance}, Path=RInfoDetailedList}">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Content="{Binding RNo}"/>
<Label Grid.Column="1" Content="{Binding DName}"/>
<Label Grid.Column="2" Content="{Binding DCExpires }"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Data from RInfo & DInfo Binds succesfully. but from RInfoDetailedList does not bind.
What is that I'm missing
This is because RInfoDetailedList is returning null due to the wrong cast!
You can create the RInfo_Details object in the select statement like this
public IEnumerable<RInfo_Details> RInfoDetailedList
{
get
{
if (RInfo == null || DInfo == null) return null;
var newList = from r in RInfo
join d in DInfo
on r.DCode equals d.DCode
select new RInfo_Details {
RCode = r.RCode,
ACode = r.ACode,
DCode = r.DCode,
DName = d.DName,
RNo = r.RNo,
};
return newList;
}
}
Related
I have a tree view which is used by 2 different sources (Mission, Target) depending on the mode the GUI is in. Only 1 source is displayed at any one time
Class information:
Mission Class
public class Mission
{
public string Name { get; set; }
public List<Target> PotentialTargets { get; set; }
public List<Target> SelectedTargets { get; set; }
public List<Operation> OpList { get; set; }
//other properties
}
Operation Class
public class Operation
{
public string Label { get; set; }
//other properties
}
Target
public class Target
{
public string Label { get; set; }
public TargetType Type { get; set; }
public int Priority { get; set; }
//other properties
}
TargetType
public enum TargetType
{
Star,
Line
}
I am trying to achieve the following display on the TreeView when setting the itemSource to a different source.
Mission Source
- Mission_1(Name)
- Potential_Target
- Target_1(Label)
- Target_2(Label)
- Selected_Target
- Target_1(Label)
- Operation
- Op_1(Name)
- Mission_2(Name)
- Potential_Target
- Target_1(Label)
- Target_4(Label)
- Selected_Target
- Target_4(Label)
- Operation
- Op_1(Name)
Target Source
- Priority_1(Priority)
- Star(TargetType)
- Star_Target_1(Label)
- Line(Type)
- Line_Target_1(Label)
- Priority_2(Priority)
- Star(TargetType)
- Star_Target_2(Label)
- Star_Target_3(Label)
All help will be appreciated.
Thanks in advance.
You need some base class to represent your tree nodes in TreeView.
For example you can declare you classes like this:
ABaseNode
// Base class to provide access to nodes Children
public abstract class ABaseNode
{
private ObservableCollection<ABaseNode> children;
public ObservableCollection<ABaseNode> Children
{
get { return children ?? (children = new ObservableCollection<ABaseNode>()); }
set { children = value; }
}
}
LabeledNode
//Simple node with label to display
public class LabeledNode : ABaseNode
{
public LabeledNode(string label)
{
Label = label;
}
public string Label { get; private set; }
}
Mission Class
public class Mission : LabeledNode
{
public Mission(string label) : base(label)
{
PotentialTargetsNode = new LabeledNode("PotentialTargets");
Children.Add(PotentialTargetsNode);
SelectedTargetsNode = new LabeledNode("SelectedTargets");
Children.Add(SelectedTargetsNode);
OpListNode = new LabeledNode("Operation");
Children.Add(OpListNode);
}
public LabeledNode PotentialTargetsNode { get; private set; }
public LabeledNode SelectedTargetsNode { get; private set; }
public LabeledNode OpListNode { get; private set; }
}
Operation Class
public class Operation : LabeledNode
{
public Operation(string label) : base(label)
{
}
//other properties
}
Target Class
public class Target : LabeledNode
{
public Target(string label) : base(label)
{
}
public TargetType Type { get; set; }
public int Priority { get; set; }
//other properties
}
PriorityNode Class
public class PriorityNode : LabeledNode
{
public PriorityNode(int priority) : base("Priority: " + priority)
{
StarTargetsNode = new LabeledNode("Star");
Children.Add(StarTargetsNode);
LineTargetsNode = new LabeledNode("Line");
Children.Add(LineTargetsNode);
}
public LabeledNode StarTargetsNode { get; private set; }
public LabeledNode LineTargetsNode { get; private set; }
}
Xaml of MainWindow contents
<StackPanel>
<Button Content="Mission source" Click="MissionButtonClick"/>
<Button Content="Target source" Click="TargetsButtonClick"/>
<TreeView x:Name="treeView" Height="250" ItemsSource="{Binding Missions}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:LabeledNode}" ItemsSource="{Binding Path=Children}">
<TextBlock Text="{Binding Path=Label}"/>
<HierarchicalDataTemplate.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:LabeledNode}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Label}"/>
</HierarchicalDataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</StackPanel>
Data initialization
public partial class MainWindow : Window
{
public ObservableCollection<Mission> Missions { get; private set; }
public ObservableCollection<PriorityNode> TargetsByPriority { get; private set; }
public MainWindow()
{
InitializeComponent();
var mission = new Mission("Mission1");
mission.PotentialTargetsNode.Children.Add(new Target("Target1") {Type = TargetType.Line, Priority = 1});
mission.PotentialTargetsNode.Children.Add(new Target("Target2") {Type = TargetType.Star, Priority = 2});
mission.SelectedTargetsNode.Children.Add(new Target ("SelectedTarget") { Type = TargetType.Line, Priority = 1 });
mission.OpListNode.Children.Add(new Operation("Op1"));
Missions = new ObservableCollection<Mission> { mission };
var priorityNode = new PriorityNode(1);
priorityNode.StarTargetsNode.Children.Add(new Target("Target3") { Type = TargetType.Star, Priority = 1 });
priorityNode.LineTargetsNode.Children.Add(new Target("Target1") { Type = TargetType.Line, Priority = 1 });
priorityNode.LineTargetsNode.Children.Add(new Target("Target2") { Type = TargetType.Line, Priority = 1 });
TargetsByPriority = new ObservableCollection<PriorityNode> { priorityNode};
DataContext = this;
}
private void MissionButtonClick(object sender, RoutedEventArgs e)
{
treeView.ItemsSource = Missions;
}
private void TargetsButtonClick(object sender, RoutedEventArgs e)
{
treeView.ItemsSource = TargetsByPriority;
}
}
Now click the buttons to change your TreeView ItemsSource.
When im displaying my database table it contains a few collections and those dont display in the datagrid. a column is generated but it stays blank. I do not know where to implement this either.
Maybe this will help also to explain what i want to display in the column instead of the ICollection
static void Main(string[] args)
{
using (var db = new Whataboutthisfish())
{
Vis vis = db.Vissen.Find(2);
if(vis != null)
{
if(vis.Continenten != null)
{
string s = "";
if(vis.Continenten.Count() > 1)
{
var continentenLijst = vis.Continenten;
s = continentenLijst.First().Naam;
foreach (Continent c in vis.Continenten)
{
s += ", "+c.Naam;
}
}
else
{
s = vis.Continenten.First().Naam;
}
Console.WriteLine(s);
}
}
}
}
I would like to return 1 string containing each continent's name using a seperator.
Like: "North-America" if there's only 1 continent in the collection
Or: "North-America, South-America" and so on for multiple.
Classes;
[Table("Continenten")]
public partial class Continent
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Continent()
{
Vissen = new HashSet<Vis>();
}
public int Id { get; set; }
[Required]
[StringLength(50)]
public string Naam { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Vis> Vissen { get; set; }
}
}
[Table("Vissen")]
public partial class Vis
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Vis()
{
Continenten = new HashSet<Continent>();
Verbanden = new HashSet<Verband>();
Waterlagen = new HashSet<Waterlaag>();
}
public int Id { get; set; }
[StringLength(200)]
public string Naam { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Continent> Continenten { get; set; }
}
The Xaml for grid:
<DataGrid x:Name="dataGrid" HorizontalAlignment="Left" VerticalAlignment="Top" RenderTransformOrigin="0.833,0.846" Margin="10,10,10,10"/>
In code behind:
using (var db = new Catattafish.Whataboutthisfish())
{
dataGrid.ItemsSource = db.Vissen.ToList();
}
I asked this before and have a solution that works:
See Answer by srithar here
Being new to XAML/WPF, that one was my instinctively preferred solution. However, experts keep on telling us: "DO NOT manipulate the GUI! Handle the model instead."
This is the relevant XAML code:
<DataGridTemplateColumn Header=" Top Plate Thickness ">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox
ItemsSource="{Binding Gauge, Mode=TwoWay}"
DisplayMemberPath="Thickness"
SelectedItem="{Binding TopPlateThickness, UpdateSourceTrigger=PropertyChanged}" SelectionChanged="ComboBoxLeft_SelectionChanged">
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="IsEnabled" Value="{Binding Enabled}"/>
</Style>
</ComboBox.ItemContainerStyle>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
It currently supports the ability to disable menu items. This is the Code Behind:
static List<string> caliber = new List<string> { "0.3750", "0.5000", "0.6250", "0.7500", "1.0000" };
string left = "";
string right = "";
PlateThicknesses(ref left, ref right, rnd);
Selectable top = new Selectable(left);
Selectable bot = new Selectable(right);
GridsModel gm = new GridsModel()
{
OuterDiameter = outerDiameter,
InnerDiameter = innerDiameter,
TopPlateThickness = top,
BottomPlateThickness = bot
};
static void PlateThicknesses(ref string leftComboBoxIndex, ref string rightComboBoxIndex)
{
int a = rnd.Next(7);
int b = rnd.Next(7);
if (a > b)
{
leftComboBoxIndex = caliber[a];
rightComboBoxIndex = caliber[b];
}
else
{
leftComboBoxIndex = caliber[b];
rightComboBoxIndex = caliber[b];
}
}
Model:
public class GridsModel : PropertyChangedBase
{
public string Item { get; set; }
public string Description { get; set; }
private int _Quantity;
public int Quantity
{
get
{
return _Quantity;
}
set
{
if (_Quantity != value)
{
_Quantity = value;
RaisePropertyChanged("Quantity");
}
}
}
private int _QtyOfFound;
public int QtyOfFound
{
get
{
return _QtyOfFound;
}
set
{
if (_QtyOfFound != value)
{
_QtyOfFound = value;
RaisePropertyChanged("QtyOfFound");
}
}
}
public double MaxBoltLoad { get; set; }
public int NumberOfBolts { get; set; }
public double Separation { get; set; }
private double _Length;
public double Length
{
get
{
return _Length;
}
set
{
if (_Length != value)
{
_Length = value;
RaisePropertyChanged("Length");
}
}
}
public double Gamma { get; set; }
public double Beta { get; set; }
public double OuterDiameter { get; set; }
public double InnerDiameter { get; set; }
public List<Selectable> Gauge { get; set; } // Gauche is "Left" in French
private Selectable _TopPlateThickness;
public Selectable TopPlateThickness
{
get
{
return _TopPlateThickness;
}
set
{
if (_TopPlateThickness != value)
{
_TopPlateThickness = value;
RaisePropertyChanged("TopPlateThickness");
}
}
}
public List<Selectable> Caliber { get; set; } // The Right Stuff
private Selectable _BottomPlateThickness;
public Selectable BottomPlateThickness
{
get
{
return _BottomPlateThickness;
}
set
{
if (_BottomPlateThickness != value)
{
_BottomPlateThickness = value;
RaisePropertyChanged("BottomPlateThickness");
}
}
}
public double BoltCircleDiameter { get; set; }
private double _TemplateSetWeight;
public double TemplateSetWeight
{
get
{
return _TemplateSetWeight;
}
set
{
if (_TemplateSetWeight != value)
{
_TemplateSetWeight = value;
RaisePropertyChanged("TemplateSetWeight");
}
}
}
public double AnchorBoltSetWeight { get; set; }
private double _WholeAnchorCageWeight;
public double WholeAnchorCageWeight
{
get
{
return _WholeAnchorCageWeight;
}
set
{
if (_WholeAnchorCageWeight != value)
{
_WholeAnchorCageWeight = value;
RaisePropertyChanged("WholeAnchorCageWeight");
}
}
}
public GridsModel()
{
Gauge = new List<Selectable> { new Selectable("0.3750"),
new Selectable("0.4375"),
new Selectable("0.5000"),
new Selectable("0.6250"),
new Selectable("0.7500"),
new Selectable("0.8650"),
new Selectable("1.0000") };
Caliber = new List<Selectable> { new Selectable("0.3750"),
new Selectable("0.4370"),
new Selectable("0.5000"),
new Selectable("0.6250"),
new Selectable("0.7500"),
new Selectable("0.8650"),
new Selectable("1.0000") };
}
}
Selectable Class:
public class Selectable : PropertyChangedBase
{
private string _Thickness;
public string Thickness
{
get
{
return _Thickness;
}
set
{
if (_Thickness != value)
{
_Thickness = value;
RaisePropertyChanged("Thickness");
}
}
}
private bool _Enabled;
public bool Enabled
{
get
{
return _Enabled;
}
set
{
if (_Enabled != value)
{
_Enabled = value;
RaisePropertyChanged("Enabled");
}
}
}
public Selectable(string thickness)
{
Thickness = thickness;
Enabled = true;
}
}
Using debugging code I can see that the desired properties are actually being assigned the desired values, but the visual UI fails to display them.
TIA
I'm using Wpf and EntityFrameWork in my project. I wanted to use DataAnnotations since it is a better way to validate the data. I managed to make it in my entity files. For example one of my entities include these:
public partial class Employee : INotifyPropertyChanged, IDataErrorInfo
{
public Employee()
{
this.Address = new HashSet<Address>();
this.Certificate = new HashSet<Certificate>();
this.ContactInformation = new HashSet<ContactInformation>();
this.Course = new HashSet<Course>();
this.Education = new HashSet<Education>();
this.EmployeeTeam = new HashSet<EmployeeTeam>();
this.Evaluation = new HashSet<Evaluation>();
this.ExamInformation = new HashSet<ExamInformation>();
this.JobTitle = new HashSet<JobTitle>();
this.MilitaryService = new HashSet<MilitaryService>();
this.Relationship = new HashSet<Relationship>();
this.WorkExperience = new HashSet<WorkExperience>();
}
public int Id { get; set; }
private string _CitizenId;
[Required(ErrorMessage = "CitizenId is required!")]
[RegularExpression(#"^\d+$", ErrorMessage = "Only numbers allowed")]
public string CitizenId
{
get
{
return _CitizenId;
}
set
{
_CitizenId = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("CitizenId"));
}
}
}
private int _RegNumber;
[Required (ErrorMessage = "Registration Number is required!")]
[RegularExpression(#"^\d+$", ErrorMessage = "Only numbers allowed")]
public int RegNumber
{
get
{
return _RegNumber;
}
set
{
_RegNumber = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("RegNumber"));
}
}
}
public Nullable<short> ResourceTypeId { get; set; }
public Nullable<short> EmployeeRoleId { get; set; }
private string _FirstName;
[Required(ErrorMessage="Name is required!")]
[RegularExpression(#"^[a-zA-Z''-'\s]{1,40}$", ErrorMessage="Numeric expressions are not allowed!")]
public string FirstName
{
get
{
return _FirstName;
}
set
{
_FirstName = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("FirstName"));
}
}
}
private string _MiddleName;
[RegularExpression(#"^[a-zA-Z''-'\s]{1,40}$", ErrorMessage = "Numeric expressions are not allowed!")]
public string MiddleName
{
get
{
return _MiddleName;
}
set
{
_MiddleName = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("MiddleName"));
}
}
}
private string _Surname;
[Required(ErrorMessage= "Surname is required!")]
[RegularExpression(#"^[a-zA-Z''-'\s]{1,40}$", ErrorMessage = "Numeric expressions are not allowed!")]
public string Surname {
get
{
return _Surname;
}
set
{
_Surname = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Surname"));
}
}
}
private int _CustomerNo;
[Required(ErrorMessage = "Customer Number is required!")]
[RegularExpression(#"^\d+$", ErrorMessage = "Only numbers allowed")]
public int CustomerNo
{
get
{
return _CustomerNo;
}
set
{
_CustomerNo = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("CustomerNo"));
}
}
}
public System.DateTime BirthDate { get; set; }
private string _BirthPlace;
[Required(ErrorMessage="Birh Place is required!")]
[RegularExpression(#"^[a-zA-Z''-'\s]{1,40}$", ErrorMessage = "Numeric expressions are not allowed!")]
public string BirthPlace
{
get
{
return _BirthPlace;
}
set
{
_BirthPlace = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("BirthPlace"));
}
}
}
public string Gender { get; set; }
public string MaritalStatus { get; set; }
public System.DateTime WorkBeginDate { get; set; }
//indicates that whether the start date is bigger than the end date which is a validation problem
// [CustomValidationsForDate("WorkBeginDate", ErrorMessage="Starting date cannot be bigger than the ending date")]
public Nullable<System.DateTime> WorkEndDate { get; set; }
private string _LogonName;
[Required(ErrorMessage = "Logon Name is required!")]
public string LogonName
{
get
{
return _LogonName;
}
set
{
_LogonName = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("LogonName"));
}
}
}
private int _DistanceToWork;
[RegularExpression(#"^\d+$", ErrorMessage = "Only numbers allowed")]
[Required(ErrorMessage="This field is required!")]
public int DistanceToWork
{
get
{
return _DistanceToWork;
}
set
{
_DistanceToWork = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("DistanceToWork"));
}
}
}
public Nullable<bool> HasInternet { get; set; }
public Nullable<bool> HasRemoteConnection { get; set; }
public int MilitaryStatus { get; set; }
public Nullable<int> DrivingLicense { get; set; }
public bool IsSmoker { get; set; }
public bool IsActive
{ get; set; }
public Nullable<System.DateTime> CreateDate { get; set; }
public string LeavingReason { get; set; }
public Nullable<System.DateTime> StartDate { get; set; }
public Nullable<System.DateTime> EndDate { get; set; }
public virtual ICollection<Address> Address { get; set; }
public virtual ICollection<Certificate> Certificate { get; set; }
public virtual ICollection<ContactInformation> ContactInformation { get; set; }
public virtual ICollection<Course> Course { get; set; }
public virtual ICollection<Education> Education { get; set; }
public virtual ICollection<EmployeeTeam> EmployeeTeam { get; set; }
public virtual ICollection<Evaluation> Evaluation { get; set; }
public virtual ICollection<ExamInformation> ExamInformation { get; set; }
public virtual ICollection<JobTitle> JobTitle { get; set; }
public virtual ICollection<MilitaryService> MilitaryService { get; set; }
public virtual ICollection<Relationship> Relationship { get; set; }
public virtual ICollection<WorkExperience> WorkExperience { get; set; }
//Following methos have been used in order to apply DataAnnotations
public event PropertyChangedEventHandler PropertyChanged;
public string Error { get { return String.Empty; } }
public string this[string property]
{
get { return ValidateProperty(this, property); }
}
public static string ValidateProperty(object instance, string propertyName)
{
PropertyInfo property = instance.GetType().GetProperty(propertyName);
object value = property.GetValue(instance, null);
List<string> errors = (from v in property.GetCustomAttributes(true).OfType<ValidationAttribute>()
where !v.IsValid(value)
select v.ErrorMessage).ToList();
return (errors.Count > 0) ? String.Join("\r\n", errors) : null;
}
}
}
So like I said I'm applying dataannotations inside the entities but what I want is doing that outside because whenever a change occurs in my database, all the entities will be refreshed so what I have here is not a dynamic structure.
So could you please help?
Thanks in advance.
Best regards.
Ege
You should create a model (view model) class and map from your entities (domain models) to the view model. AutoMapper can help speed this up. You then put your annotations on your view models and use these in your views.
This means that if your entity model changes you just need to update the mapping. It also means that you can create multiple different models for the same entity so your validation doesn't have to be the same for each view that uses it.
So I have the following model:
public class Person
{
public String FirstName { get; set; }
public String LastName { get; set; }
public String Address { get; set; }
public String EMail { get; set; }
public String Phone { get; set; }
}
public class Order
{
public Person Pers { get; set;}
public Product Prod { get; set; }
public List<Person> AllPersons { get; set; }
public Order(Person person, Product prod )
{
this.Pers = person;
this.Prod = prod;
AllPersons = database.Persons.GetAll();
}
}
And I have a WPF window used to edit an order.
I set the DataContext to Order.
public SetDisplay(Order ord)
{
DataContext = ord;
}
I have the following XAML:
<ComboBox Name="myComboBox"
SelectedItem = "{Binding Path=Pers, Mode=TwoWay}"
ItemsSource = "{Binding Path=AllPersons, Mode=OneWay}"
DisplayMemberPath = "FirstName"
IsEditable="False" />
<Label Name="lblPersonName" Content = "{Binding Path=Pers.FirstName}" />
<Label Name="lblPersonLastName" Content = "{Binding Path=Pers.LastName}" />
<Label Name="lblPersonEMail" Content = "{Binding Path=Pers.EMail}" />
<Label Name="lblPersonAddress" Content = "{Binding Path=Pers.Address}" />
However, the binding does not seem to work.......When I change the selected item , the labels do not update ....
Regards!!
Any reply is appreciated !!
Your model will need to fire change notifications. See INotifyPropertyChanged and INotifyCollectionChanged.
For INotifyPropertyChanged, you could use a base ViewModel class such as this one. For collections, ObservableCollection<T> does the hard work for you. However, in your case your collection won't change after the UI is bound to it, so you shouldn't need an observable collection. Regardless, I'd generally recommend using observable collections in your view model layer to save head-scratching should the code ever change.
An example of what this would look like is:
public class Person : ViewModel
{
private string firstName;
private string lastName;
private string email;
private string phone;
public string FirstName
{
get
{
return this.firstName;
}
set
{
if (this.firstName != value)
{
this.firstName = value;
OnPropertyChanged(() => this.FirstName);
}
}
}
public string LastName
{
get
{
return this.lastName;
}
set
{
if (this.lastName != value)
{
this.lastName = value;
OnPropertyChanged(() => this.LastName);
}
}
}
// and so on for other properties
}
public class Order : ViewModel
{
private readonly ICollection<Person> allPersons;
private Person pers;
private Product prod;
public Person Pers
{
get
{
return this.pers;
}
set
{
if (this.pers != value)
{
this.pers = value;
OnPropertyChanged(() => this.Pers);
}
}
}
public Product Prod
{
get
{
return this.prod;
}
set
{
if (this.prod != value)
{
this.prod = value;
OnPropertyChanged(() => this.Prod);
}
}
}
// no need for setter
public ICollection<Person> AllPersons
{
get
{
return this.allPersons;
}
}
public Order(Person person, Product prod )
{
this.Pers = person;
this.Prod = prod;
// no need for INotifyCollectionChanged because the collection won't change after the UI is bound to it
this.allPersons = database.Persons.GetAll();
}
}