Silverlight datagrid bind nested object property - silverlight

I am totally new to Sivlerlight world, so I need to know a simple thing.
how do I bind nested object as Item Source to the DataGrid.
I have a class Employee which looks Like :
Public class Employee
{
public long EmployeeId
{
get
{
return this._employeeId;
}
set
{
this._employeeId = value;
}
}
public string EmployeeName
{
get
{
return this._employeeName;
}
set
{
this._employeeName = value;
}
}
public tblDepartment tblDepartment
{
get
{
return this._tblDepartment;
}
set
{
this._tblDepartment = value;
}
}
}
now the class "tblDepartment" has Department name as its one of the properties, so what I want to achieve is show EmployeeId, EmployeeName and Department name in the DataGrid of Silverlight. I am using SilverLight 4.0.
Issue is I am not able to find how to bind Nested objects properties(i.e. Objects with in Objects).
can anyone help me out here,
thanks in advance.

You should be able to do
{Binding Path=EmployeeObject.tblDepartment.Name}

Related

Databinding not refreshed in Xamarin (WPF)

I have some trouble with the data binding while using MVVM in Xamarin. Let me explain my architecture:
I have a Manager-class, which contains a ObservableCollection with classes of type t, t is my model class. The Manager-class contains also a attribute called activeT, which is the current selected object of my model class. There are 2 UIs, one which shows the current data of t. The viewModel is bound to the attribute t of my Manager-class like that:
public t CurrentT
{
get
{
return _mgr.CurrentT;
}
set
{
_mgr.CurrentT = value;
OnPropertyChanged();
}
}
_mgr is my singleton Manager-Object.
Now there is the other view, which is able to choose the current t out of a combobox. The viewModel of that view is bound to the ObservableCollection of the manager. If I change the selected object, I do it like with the same code like above. The Property of the manager is the following code:
public t CurrentT
{
get
{
return _currentT;
}
set
{
_currentT= value;
OnPropertyChanged());
}
}
The problem is now, that the first view to view the current selected t does not refresh, though I can see in the debugger, that the current t is changed by the other view.
Can someone help me?
Edit:
I provide some more Code:
The Manager-Class:
public class Manager : INotifyPropertyChanged
{
private t _currentConstructionSite;
private ObservableCollection<t> _constructionSites = null;
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(name));
}
public t CurrentConstructionSite
{
get
{
return _currentConstructionSite;
}
set
{
_currentConstructionSite = value;
OnPropertyChanged("CurrentConstructionSite");
}
}
public ObservableCollection<t> ConstructionSites
{
get
{
return _constructionSites;
}
set
{
_constructionSites = value;
}
}
private Manager()
{
ConstructionSites = DataRepository.GenConstructionSites();
_currentConstructionSite = ConstructionSites[0];
}
}
The ViewModels Class A (This is the viewmodel of the view, which shows some data):
public class DashboardViewModel : ViewModelBase
{
private Manager _mgr;
public t CurrentConstructionSite
{
get
{
return _mgr.CurrentConstructionSite;
}
set
{
_mgr.CurrentConstructionSite = value;
OnPropertyChanged();
}
}
public DashboardViewModel()
{
_mgr = Manager.getInstance();
}
}
The View A to show some data:
Binding Setup from XAML:
<ContentPage.BindingContext>
<local:DashboardViewModel x:Name="viewModel"/>
</ContentPage.BindingContext>
Binding a Label to show data:
<Label Text="{Binding CurrentConstructionSite.ConstructionSiteName, Mode=TwoWay}" HorizontalOptions="Center" Font="Bold" FontSize="Large"/>
ViewModel B to choose the current t:
public class ChooseConstructionSiteViewModel : ViewModelBase
{
Manager _mgr = null;
public ObservableCollection<t> ConstructionSites
{
get
{
return _mgr.ConstructionSites;
}
}
public t CurrentConstructionSite
{
get
{
return _mgr.CurrentConstructionSite;
}
set
{
_mgr.CurrentConstructionSite = value;
OnPropertyChanged();
}
}
public ChooseConstructionSiteViewModel()
{
_mgr = Manager.getInstance();
}
}
The View to choose the current t:
<combobox:SfComboBox x:Name="combobox" Grid.Row="0" Grid.Column="1" Margin="8,0,20,0" VerticalOptions="Center" HeightRequest="40" DataSource="{Binding ConstructionSites}" DisplayMemberPath="ConstructionSiteName" SelectionChanged="Handle_SelectionChanged"/>
And if the selection from the combobox changed:
void Handle_SelectionChanged(object sender, Syncfusion.XForms.ComboBox.SelectionChangedEventArgs e)
{
t selectedItem = e.Value as t;
_viewModel.CurrentConstructionSite = selectedItem;
}
The two views are contained as contetPages in a tabbedPage. It works in general, but the changing the selected t in the view B does not update the data in view A. I can see in the debugger that the value of t is changed via view B but when I go back to view A there is the old value. In the debugger I can see that the value is updated.
BTW: ViewModelBase is the class which implements INotifyPropertyChanged
From you second viewmodel, you need to "notify" the first viewmodel that the data has changed.
One of the ways to do that, would be to use a Messenger (MvvmLight has one, so does MvvmCross). You can then use the messenger from your Manager, to notify all the viewmodels that need the info, that CurrentT changed.
In the messenger subscription in your viewmodels, simply call a RaiseNotifyPropertyChanged of your property, and you should be good to go

How to use ReactiveList so UI is updated when items are added/removed/modified

I'm creating a WinForms application with a DataGridView. The DataSource is a ReactiveList. Adding new items to the list however does not update the UI.
ViewModel
public class HomeViewModel: ReactiveObject
{
public ReactiveCommand<object> AddCmd { get; private set; }
ReactiveList<Model> _models;
public ReactiveList<Model> Models
{
get { return _models; }
set { this.RaiseAndSetIfChanged(ref _models, value); }
}
public HomeViewModel()
{
Models = new ReactiveList<Model>() { new Model { Name = "John" } };
AddCmd = ReactiveCommand.Create();
AddCmd.ObserveOn(RxApp.MainThreadScheduler);
AddCmd.Subscribe( _ =>
{
Models.Add(new Model { Name = "Martha" });
});
}
}
public class Model
{
public string Name { get; set; }
}
View
public partial class HomeView : Form, IViewFor<HomeViewModel>
{
public HomeView()
{
InitializeComponent();
VM = new HomeViewModel();
this.OneWayBind(VM, x => x.Models, x => x.gvData.DataSource);
this.BindCommand(VM, x => x.AddCmd, x => x.cmdAdd);
}
public HomeViewModel VM { get; set; }
object IViewFor.ViewModel
{
get { return VM; }
set { VM = (HomeViewModel)value; }
}
HomeViewModel IViewFor<HomeViewModel>.ViewModel
{
get { return VM; }
set { VM = value; }
}
}
The view always show "John".
Debugging Subscribe show added items.
Tried it with ObservableCollection same result.How to use ReactiveList so UI is updated when new items are added
Tried it with IReactiveDerivedList same result. Does ReactiveUI RaiseAndSetIfChanged fire for List<T> Add, Delete, Modify?
I think what you want is a ReactiveBindingList rather than a ReactiveList. This is a WinForms specific version of the ReactiveList for binding purposes.
You should use BindingList.
reference :
"If you are bound to a data source that does not implement the IBindingList interface, such as an ArrayList, the bound control's data will not be updated when the data source is updated. For example, if you have a combo box bound to an ArrayList and data is added to the ArrayList, these new items will not appear in the combo box. However, you can force the combo box to be updated by calling the SuspendBinding and ResumeBinding methods on the instance of the BindingContext class to which the control is bound."
https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-bind-a-windows-forms-combobox-or-listbox-control-to-data?view=netframeworkdesktop-4.8
Or
ReactiveBindingList
It work fine for me. !!!

How can I bind collection data as a columns value in a datagrid?

I want to bind a collection of data as different columns in a DataGrid. The normal way we bind data is bind property. But now my scenario is the properties is a dynamic collection which might be different from different object instances. For each object I need dynamically create a DataGrid.
Here I give a simplified live example which is abstracted from my scenario :
public class Company
{
...
public string CompanyName { set; get; }
public ObservableCollection<CompanyProperty> data;
}
public class CompanyProperty
{
public string PropertyName { get; set; }
public string Value { get; set; }
}
In my main class, I have a ObservableCollection of Company:
class Window
{
private ObservableCollection<Company> _list;
private void CreateData()
{
Company tmp = new Company("Siemens");
tmp.data.Add(new CompanyProperty() { PropertyName = "Country", Value = "Germany" });
tmp.data.Add(new CompanyProperty() { PropertyName = "Staffs", Value = "400,000" });
_list.Add(tmp);
tmp = new Company("ABB");
tmp.data.Add(new CompanyProperty() { PropertyName = "Country", Value = "Swiss" });
tmp.data.Add(new CompanyProperty() { PropertyName = "Staffs", Value = "100,000" });
_list.Add(tmp);
}
}
Now I want to bind my data to a DataGrid which will be looked like 3 columns(CompanyName, Country, Staffs) and 2 rows(Siemens, ABB).
What I'm struggling with is how to bind the collection of company properties to the different columns in my DataGrid since the "Country" and "Staffs" is not properties of "Company" class but only values in an ObservableCollection member.
After some investigation I figured out a solution myself, that is create a DataTable transfer the collection data to the DataTable (we can easily change the values into different columns in the DataTable).
Then instead of bind the "ObservableCollection _list" we bind the DataTable to the datagrid. This seems works.
And I'm still interested to know if someone got some other or better solutions for the kind of senario?

observableCollection: how to establish type in runtime?

I have a dataGrid, that uses an observableCollection to bind the ItemsSource property (MVVM pattern). So in my viewmodel I have a property that is an observableCollection (myCollection). However, this dataGrid can show information of two different types, that their are decide in runtime.
Normally, I use the the observableCollection in this away:
ObservableCollection<myType> myCollection = new ObservableCollection<myType>();
But now, I have a string as parameter that say me what type I need, so I would like to do something like that:
if(parameter == "TypeA")
{
myCollection = new ObservableCollection<TypeA>();
}
if(parameter == "TypeB")
{
myCollection = new ObservableCollection<TypeB>();
}
is it possible to do that?
If you make TypeA and TypeB derived from a common base class or interface, you can keep the same collection.
But if you want two different collections, you you can raise the collection property to notify about the changed type.
IEnumerable MyCollection
{
get
{
if(CurrentType == typeof(TypeB)
return myTypeBCollection;
else if(CurrentType == typeof(TypeA)
return myTypeACollection;
}
}
So your bind MyCollection in your view to ItemsSource, and raise that the property has changed.
Remember that you might need a different DataTemplate, where a DataTemplateSelector might come in handy.
Just Use the dynamic Keyword instead of Exact Type for Declaring ObservableCollection in Runtime
private ObservableCollection<dynamic> DynamicObservable(IEnumerable source)
{
ObservableCollection<dynamic> SourceCollection = new ObservableCollection<dynamic>();
SourceCollection.Add(new MobileModelInfo { Name = "iPhone 4", Catagory = "Smart Phone", Year = "2011" });
SourceCollection.Add(new MobileModelInfo { Name = "S6", Catagory = "Ultra Smart Phone", Year = "2015" });
return SourceCollection;
}
public class MobileModelInfo
{
public string Name { get; set; }
public string Catagory { get; set; }
public string Year { get; set; }
}

Binding Custom Object Datagrid Silverlight 4

I create an object Custom as you can see below
public class GridViewModel
{
private List _listRowCust = new List();
public List ListRowCust
{
get { return _listRowCust; }
set { _listRowCust = value; }
}
}
public class RowCustom
{
private List<CellCustom> _listCellCustom = new List<CellCustom>();
public List<CellCustom> ListCellCustom
{
get { return _listCellCustom; }
set { _listCellCustom = value; }
}
public RowCustom() { }
}
I try to bind the custom object on the datagrid object available in silverlight4.
I wish to bind any cell on the datagrid. One line should identify by a row object and each cell by a cellCustom.
I use this code
textColumn = new DataGridTextColumn();
textColumn.Header = "RemainingWork";
textColumn.Binding = new Binding("Cell[0]"); //it's a supposed syntax possibility in fact I have 3 rows with 10 cells
GridElements.Columns.Add(textColumn);
GridElements.ItemsSource = e.GridViewModel.ListRowCust;
I don't find any explanation on How to custom the binding.
Do you have any idea?
Thank you
best regards,
Alexandre
I think you can only bind to public properties.
So CellCustom must have a public property to bind to, if that's the object used for the itemsSource, or data context.

Resources