Problem with binding Stacked colums series chart to Series - wpf

i have big problem with binding Stacked Column Series to my chart.
I have
public ObservableCollection Series property in my ViewModel and try by many ways but it still not working.
This is code from ViewModel to prepare Series:
private void drawChart()
{
this.Series.Clear();
var dataValues = new List<List<SimpleDataValue>>();
int wartoscNiezalezna = 1;
for (int i = 0; i < 2; i++)
{
dataValues.Add(new List<SimpleDataValue>());
}
foreach (var item in myCollection)
{
var param = someparam;
dataValues[0].Add(new SimpleDataValue { IndependentValue = "Czujnik " + wartoscNiezalezna, DependentValue = 100 });
//czerwone
dataValues[1].Add(new SimpleDataValue { IndependentValue = "" + wartoscNiezalezna, DependentValue = 200 });
wartoscNiezalezna++;
}
var stackedSeries = Activator.CreateInstance(typeof(StackedColumnSeries)) as DefinitionSeries;
int itemnr=0;
foreach (var item in dataValues)
{
var definicja = new SeriesDefinition();
if(itemnr==0)
definicja.Title = "Stan 1";
else
definicja.Title = "Stan 2";
definicja.DependentValuePath = "DependentValue";
definicja.IndependentValuePath = "IndependentValue";
definicja.ToolTip = "asdas";
definicja.ItemsSource = item;
stackedSeries.SeriesDefinitions.Add(definicja);
itemnr++;
}
Series.Add(stackedSeries);
}
I cant bind it to:
<charting:Chart x:Name="MyChart" Padding="10,10,10,10">
<charting:Chart.Series>
<charting:StackedColumnSeries>
<charting:SeriesDefinition ItemsSource="{Binding Series}" DependentValuePath="DependentValue" IndependentValuePath="IndependentValue">
</charting:SeriesDefinition>
</charting:StackedColumnSeries>
</charting:Chart.Series>
</charting:Chart>
I was trying with SeriesDefinitions Collection and others.
I will be very grateful to some help.

I hope I've answered your question there
Anyway I post the second part of my answer here:
MainWindow.xaml:
<charting:Chart x:Name="MyChart" Padding="10,10,10,10">
<charting:Chart.Series>
<charting:StackedColumnSeries>
<charting:SeriesDefinition Title="Stan 1" ItemsSource="{Binding FirstCollection}" DependentValuePath="DependentValue" IndependentValuePath="IndependentValue" />
<charting:SeriesDefinition Title="Stan 2" ItemsSource="{Binding SecondCollection}" DependentValuePath="DependentValue" IndependentValuePath="IndependentValue" />
</charting:StackedColumnSeries>
</charting:Chart.Series>
</charting:Chart>
MainWindow.xaml.cs
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
this.MyChart.DataContext = new ChartModel
{
FirstCollection = Enumerable.Range(1, 10).Select(i => new SimpleDataValue { IndependentValue = "Czujnik " + i, DependentValue = 100 }).ToList(),
SecondCollection = Enumerable.Range(1, 10).Select(i => new SimpleDataValue { IndependentValue = "" + i, DependentValue = 200 }).ToList()
};
}
}
public class SimpleDataValue
{
public string IndependentValue { get; set; }
public int DependentValue { get; set; }
}
public class ChartModel
{
public List<SimpleDataValue> FirstCollection { get; set; }
public List<SimpleDataValue> SecondCollection { get; set; }
}

I am not sure with the syntax but the logic should be like below:
ViewModel
public class GraphItem {
public string IndependentValue { get; set; }
public int DependentValue1 { get; set; }
public int DependentValue2 { get; set; }
}
public class ChartViewModel
{
private List<GraphItem> itemCollection;
public List<GraphItem> ItemCollection
{
get { return itemCollection;}
set {
itemCollection=value;
OnPropertyChanged("ItemCollection");
}
}
public ChartViewModel()
{
//Bind ItemCollection
}
}
Xaml:
<charting:Chart x:Name="MyChart" Padding="10,10,10,10" DataContext={Binding ItemCollection}">
<charting:Chart.Series>
<charting:StackedColumnSeries>
<charting:SeriesDefinition Title="Stan 1" ItemsSource="{Binding}" DependentValuePath="DependentValue1" IndependentValuePath="IndependentValue" />
<charting:SeriesDefinition Title="Stan 2" ItemsSource="{Binding}" DependentValuePath="DependentValue2" IndependentValuePath="IndependentValue" />
</charting:StackedColumnSeries>
</charting:Chart.Series>
</charting:Chart>
May this help.

Related

Unable to Bind ListBox to IEnumerable<object>

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;
}
}

WPF treeview with databinding using multiple data sources

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.

How to return a string in the dataGrid.ItemsSource when it contains a ICollection<Continent>

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();
}

Correct way to data-bind collections to ComboBox in WPF using MVVM?

I'm using MVVM pattern, developing my WPF application. I also use Entity Framework as ORM. Here're my models (EF):
public class User : BaseEntity
{
public string Name { get; set; }
public int OfficeId { get; set; }
public Office Office { get; set; }
}
public class Office : BaseEntity
{
public string Name { get; set; }
public int DepartmentId { get; set; }
public Department Department { get; set; }
public virtual ICollection<User> Users { get; set; }
}
public class Department : BaseEntity
{
public string Name { get; set; }
public virtual ICollection<Office> Offices { get; set; }
}
Let's assume, that I've got an instance of User class from my context:
var userInstance = context.Get<User>().Single(user => user.ID == 1);
Now I'd like to pass this instance to my View to make some changes for concrete user (called, for example, UserEditView), so I have to create a UserModel class to deal with User data according to MVVM. So, here's what I think I have to write in my code:
public class UserModel : ObservableObject
{
private User user;
public string Office Office
{
get
{
return this.user.Office.Name;
}
set
{
//what shoud I write Here??
if(value != user.Office)
{
user.Office=value;
OnPropertyChanged("Office");
}
}
}
}
I'm really frustrated! How should I deal with that? There're thousands of examples, but they are so simple. I'm wondering what should I do to have a ComboBox in my EditView with a list of all Offices, existing in my DB. And list of Offices should depend on another one Combobox, which contains a list of Departments.
But where should I get this lists from?
Should I pass a collection from my UserModel? Or what?
Can anybody give me a simple example about how to do this correctly?
PS: Of course, I know couple ways to implement such behaviour, but in that case my code seems to be ugly and not maintainable. Please, help. Thanks a lot!
this is depends on your DB architecture. Here is some common suggestion (but there can be a lot of others).
Don't panic - you have a correct question.
Create the view model set it to be a main view model of your window.
In your view model create two collections Users (containing UserModels) and Departments (containing DepartmentMode), since you want to change offices each time you re-select department, you don't need the Offices collection in main view model.
Pull each collection data from your data base.
Implement each model with INPC.
Take in account the WPF MVVM best practices.
Apply a correct bindings.
And be happy - you are a programmer.
Updates - 1
XAML code
<Grid x:Name="LayoutRoot">
<Grid.DataContext>
<someBindingExampleSoHelpAttempt:MainViewModel/>
</Grid.DataContext>
<ListView ItemsSource="{Binding Users}">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate DataType="someBindingExampleSoHelpAttempt:UserModel">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="200"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
<ColumnDefinition Width="50"></ColumnDefinition>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="{Binding Name, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
<TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="{Binding LastName, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
<ComboBox Grid.Column="2"
IsTextSearchEnabled="True"
IsTextSearchCaseSensitive="False"
StaysOpenOnEdit="True"
TextSearch.TextPath="DepartmentName"
ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor,
AncestorType={x:Type ListView}}, Path=DataContext.Departments}"
SelectedValue="{Binding Department}"
DisplayMemberPath="DepartmentName"
IsEditable="True"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
<ComboBox Grid.Column="3"
IsTextSearchEnabled="True"
IsTextSearchCaseSensitive="False"
StaysOpenOnEdit="True"
IsEditable="True"
TextSearch.TextPath="OfficeName"
ItemsSource="{Binding OfficesCollection}"
SelectedValue="{Binding Office}"
DisplayMemberPath="OfficeName"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"/>
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.ItemContainerStyle>
</ListView></Grid>
VM and models
public class MainViewModel:BaseObservableObject
{
private DepartmentModel _selectedDepartment;
private OfficeModel _selectedOffice;
public MainViewModel()
{
Dal = new DataLayer();
Users = new ObservableCollection<UserModel>();
Departments = new ObservableCollection<DepartmentModel>(Dal.GetAllDepartments());
InitUsersCollection();
}
private void InitUsersCollection()
{
if(Departments == null) return;
Departments.ToList().ForEach(model =>
{
model.Offices.ToList().ForEach(officeModel =>
{
if (officeModel.Users == null) return;
officeModel.Users.ToList().ForEach(userModel => Users.Add(userModel));
});
});
}
public ObservableCollection<UserModel> Users { get; set; }
public ObservableCollection<DepartmentModel> Departments { get; set; }
private DataLayer Dal { get; set; }
}
public class DataLayer
{
public List<DepartmentModel> GetAllDepartments()
{
//pull and map your using your DB service
//For example:
return new List<DepartmentModel>
{
new DepartmentModel
{
DepartmentId = 1,
DepartmentName = "A",
Offices = new ObservableCollection<OfficeModel>
{
new OfficeModel
{
DepartmentId = 1,
OfficeName = "AA",
Users = new ObservableCollection<UserModel>(new List<UserModel>
{
new UserModel {Name = "Avicenna", LastName = "Abu Ali Abdulloh Ibn-Sino"},
new UserModel {Name = "Omar", LastName = "Khayyam"},
new UserModel {Name = "RAMBAM", LastName = "Moshe ben Maimon"}
})
},
new OfficeModel
{
DepartmentId = 1,
OfficeName = "AB",
Users = new ObservableCollection<UserModel>(new List<UserModel>
{
new UserModel {Name = "Leo", LastName = "Tolstoi"},
new UserModel {Name = "Anton", LastName = "Chekhov"},
})},
}
},
new DepartmentModel
{
DepartmentId = 2,
DepartmentName = "B",
Offices = new ObservableCollection<OfficeModel>
{
new OfficeModel
{
DepartmentId = 2, OfficeName = "BA",
Users = new ObservableCollection<UserModel>(new List<UserModel>
{
new UserModel {Name = "B", LastName = "O"},
new UserModel {Name = "B", LastName = "N"},
}),
},
new OfficeModel
{
DepartmentId = 2, OfficeName = "BB",
Users = new ObservableCollection<UserModel>(new List<UserModel>
{
new UserModel {Name = "John", LastName = "Walker"},
new UserModel {Name = "Gregory", LastName = "Rasputin"},
}),
},
}
},
new DepartmentModel
{
DepartmentId = 3,
DepartmentName = "C",
Offices = new ObservableCollection<OfficeModel>
{
new OfficeModel {DepartmentId = 3, OfficeName = "CA"},
new OfficeModel {DepartmentId = 3, OfficeName = "CB"},
new OfficeModel {DepartmentId = 3, OfficeName = "CC"}
}
}
};
}
}
public class OfficeModel:BaseObservableObject
{
private int _departmentModel;
private string _officeName;
private DepartmentModel _department;
private ObservableCollection<UserModel> _users;
public int DepartmentId
{
get { return _departmentModel; }
set
{
_departmentModel = value;
OnPropertyChanged();
}
}
public DepartmentModel Department
{
get { return _department; }
set
{
_department = value;
OnPropertyChanged();
}
}
public string OfficeName
{
get { return _officeName; }
set
{
_officeName = value;
OnPropertyChanged();
}
}
public ObservableCollection<UserModel> Users
{
get { return _users; }
set
{
_users = value;
OnPropertyChanged(()=>Users);
}
}
}
public class DepartmentModel:BaseObservableObject
{
private string _departmentName;
public string DepartmentName
{
get { return _departmentName; }
set
{
_departmentName = value;
OnPropertyChanged();
}
}
public int DepartmentId { get; set; }
public ObservableCollection<OfficeModel> Offices { get; set; }
}
public class UserModel:BaseObservableObject
{
private string _name;
private string _lastName;
private DepartmentModel _department;
private OfficeModel _office;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
}
}
public string LastName
{
get { return _lastName; }
set
{
_lastName = value;
OnPropertyChanged();
}
}
public DepartmentModel Department
{
get { return _department; }
set
{
_department = value;
OnPropertyChanged();
OnPropertyChanged(()=>OfficesCollection);
}
}
public ObservableCollection<OfficeModel> OfficesCollection
{
get { return Department.Offices; }
}
public OfficeModel Office
{
get { return _office; }
set
{
_office = value;
OnPropertyChanged();
}
}
}
/// <summary>
/// implements the INotifyPropertyChanged (.net 4.5)
/// </summary>
public class BaseObservableObject : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> raiser)
{
var propName = ((MemberExpression)raiser.Body).Member.Name;
OnPropertyChanged(propName);
}
protected bool Set<T>(ref T field, T value, [CallerMemberName] string name = null)
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
OnPropertyChanged(name);
return true;
}
return false;
}
}
But please take in account that this is only one of hundreds ways to do that.
The SO here if you will need the code example.
Regards.

Why is not ICollectionView refreshed?

I cant figureout why my ICollectionView is not refreshed. Can anyone explain what I'm doing wrong?
I've made a viewmodel like this:
class ViewModel : INotifyPropertyChanged
{
private ObservableCollection<Entity> m_entities = new ObservableCollection<Entity>();
public ICollectionView EntitiesView { get; private set; }
public ICollectionView HighCountView { get; private set; }
public ViewModel()
{
m_entities.Add(new Entity() { Id = 1, Name = "Erik", Description = "The first" });
m_entities.Add(new Entity() { Id = 2, Name = "Olle", Description = "The second" });
m_entities.Add(new Entity() { Id = 3, Name = "Kim", Description = "The last" });
EntitiesView = CollectionViewSource.GetDefaultView(m_entities);
EntitiesView.CurrentChanged += new EventHandler(EntitiesView_CurrentChanged);
HighCountView = new CollectionView(m_entities);
using (HighCountView.DeferRefresh())
{
HighCountView.Filter = e => ((Entity)e).Count > 3;
}
}
private void EntitiesView_CurrentChanged(object sender, EventArgs e)
{
Entity current = EntitiesView.CurrentItem as Entity;
if(current!=null)
{
current.Count++;
HighCountView.Refresh(); // Do I need this line?
OnPropertyChanged("HighCountView"); // or this?
}
}
...and in my window I use it as the datacontext, like this:
public partial class MainWindow : Window
{
private ViewModel vm = new ViewModel();
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
this.DataContext = vm;
}
}
...and I'm doing my bindings in the XAML-code like this:
<ListBox Grid.Column="0" x:Name="listView1" DisplayMemberPath="Name" ItemsSource="{Binding EntitiesView}" IsSynchronizedWithCurrentItem="True" />
<ListView Grid.Column="1" x:Name="listView2" DisplayMemberPath="Name" ItemsSource="{Binding HighCountView}" IsSynchronizedWithCurrentItem="True" />
The problem is that all three Entities is always shown in listView2 despite that I set the Filter-property. Why?
EDIT
To made the sample complete, here is the Entity-class.
class Entity : INotifyPropertyChanged
{
private int m_id;
public int Id
{
bla bla.....
}
private string m_name;
public string Name
{
bla bla.....
}
private string m_description;
public string Description
{
bla bla.....
}
private int m_count;
public int Count
{
get { return m_count; }
set
{
if (value != m_count)
{
m_count = value;
OnPropertyChanged("Count");
}
}
}
public void Update()
{
Description = "Updated: " + (++Count).ToString() + " times.";
}
At last I found what was wrong.
If I change the line:
HighCountView = new CollectionView(m_entities);
to this
HighCountView = new ListCollectionView(m_entities);
then it works a expected.
I can also remove this line
OnPropertyChanged("HighCountView"); // or this?
I hope this can help somebody!

Resources