I am developing a WPF application in which I have a class 'Movie' which contain some properties and another class MovieCollection(which is the collection of movie). Right now I have bind this collection with my DataGrid in xaml to show Movie properties. I am taking user input by opening new window at run time and populate the observable collection with that to show it in my DataGrid, but now I want to store data in database first and fetch that data from database to show it in DataGrid. MovieCollection class is something like this
ObservableCollection<Movie> _movieObservableCollection=new ObservableCollection<Movie> ();
public ObservableCollection<Movie> MovieObservableCollection
{
get { return _movieObservableCollection; }
set
{
_movieObservableCollection = value;
this.NotifyPropertyChanged("MovieObservableCollection");
}
}
Here I want to set this collection such that the properties of model class shown as the columns attributes of the table.
How can I do this?
How can I proceed with this?
Any link?
If you bind this collection to your DataGrid, you can make use of the AutoGenerateColumns property.
<DataGrid ItemsSource="{Binding MovieObservableCollection}"
AutoGenerateColumns="True"
...
For more information, see the documentation.
Related
I have an application that allows the user to create multiple instances of the same user control that contains a listview which is bound to an ObservableCollection of a custom data type. Upon the user clicking the header I have the listview sorting correctly however it sorts all the views bound to the ObservableCollection.
My question is, is there any way to implement sorting on the view separate of the ObservableCollection, or is there another way to clone the contents of the ObservableCollection (Note: The ObservableCollection is constantly being added to by a service in the background which must be displayed in real-time).
I am sorting the collection as follows:
ICollectionView dataView = CollectionViewSource.GetDefaultView(sourceList.ItemsSource);
dataView.SortDescriptions.Clear();
SortDescription sd = new SortDescription(sortBy, direction);
dataView.SortDescriptions.Add(sd);
My list view's item source is set as follows:
myListView.ItemsSource = ServiceManager.Instance.ActiveObjects;
I would prefer not maintaining multiple instances of the same ObservableCollection. It is a requirement that the user be capable of having multiple instances of this user control so unfortunately I cannot get around this the easy way and limit them to a single instance.
Any help on this would be much appreciated, Thanks in advance.
Your mistake is setting the ItemsSource property directly to the ServiceManager.Instance.ActiveObjects property:
myListView.ItemsSource = ServiceManager.Instance.ActiveObjects;
Instead, you should create a separate ICollectionView instance from the data collection for each ListView. This example was adapted from the page linked below:
private ICollectionView _customerView;
public ICollectionView Customers
{
get { return _customerView; }
}
public CustomerViewModel()
{
IList<YourClass> customers = ServiceManager.Instance.ActiveObjects;
_customerView = CollectionViewSource.GetDefaultView(customers);
}
...
<ListBox ItemsSource="{Binding Customers}" />
You can find out further details from the How to Navigate, Group, Sort and Filter Data in WPF page on the WPF Tutorial.NET website.
I've got a Windows 8 Store form with multiple controls, a.o. lots of comboboxes, 2 I show below. I can populate them using databinding to a number of ObservableCollections (most used in multiple comboboxes, like prMachType). This works to databind the content to display.
<ComboBox x:Name="machinetype" ItemsSource="{Binding prMachtype}" SelectedItem="{Binding SelectedClass, Mode=TwoWay}" />
However I am not sure how to get the results of the controls the user enters into another ObservableCollection. The 'set' below is called (only when I add Mode=TwoWay in the XAML) when I change a value in the combobox machinetype:
public SchwDescr SelectedClass
{
get
{
return _SelectedClass;
}
set
{
if (_SelectedClass != value)
{
_SelectedClass = value;
RaisePropertyChanged("SelectedClass");
}
}
}
_SelectedClass contains the properties of the assigned ObservableCollection (like Description and Key) but now I would need to have this key (e.g. "00005") and field used (machinetype, as in the name of the combobox) together to store in another ObservableCollection (containing Field + Key, so machinetype and "00005" when this combobox is selected. I do not see which control (here combobox machinetype) the user is changing here so I can't store the field+selection 'manually' and I also don't see how I can databind directly to such an ObservableCollection so key+field are update directly and also show the (stored) selection when I load the data again (the preferred way of course).
Can someone lead me to the right direction (like a full sample)?
I have the following service class:
public class MyService
{
List<MyModel> GetData() { .... }
void Save(List<MyModel> changedRows) { .... }
}
Is it possible to bind the data source of the DataGridView to the list returned by myService.GetDate(); and then user edit in the DataGridView and click a "SaveAll" button to commit all the changes by calling the function myService.Save(???)?
Is it possible to get a list of the changed rows and pass it to myService.Save(list)?
This seems a common issue but I cannot find much information. Am I using the wrong approach?
Couple options I can think of:
1) You can wrap the MyModel class inside a MyModelView class that includes a MyModel property and a Status enum property (inserted, updated, deleted). When you get the List<MyModel>, you can create and fill a List<MyModelView> and bind that new list to the datagridview. Any time the user edits a row, you update the Status property according to the user action (inserted, updated, deleted). Note that this also requires some extra work for filtering out the deleted rows, as you probably don't want the deleted rows to be displayed.
2) You'd bind the List<MyModel> directly to the datagridview, but have a seperate List<MyModelView> that only includes changed rows. Any time there is a change, you'd track the change in this separate list.
I have a MVVM application with a MainWindowViewModel connected to a MainWindowview.
On the MainWindow view I have a ComboBox containing stock ticker symbols.
I have another viewmodel and view called AllStockQuoteViewModel connected to AllStockQuoteView which contains a list of stocks and their prices.
I want to be able to select an item from the ComboBox and have the item in the AllStockQuoteView selected and highlighted. On my MainWindowViewModel I have saved the reference to the AllStockQuoteViewModel and use it to call a method to find the stock ticker symbol in the ObservableCollection bound to the AllStockQuoteView, but haven't found a way to programmatically select the item on the AllStockQuoteView.
I have a SelectedQuote property on the AllStockQuoteViewModel bound to the listview on the AllStockQuoteView and I can select one of the items and my SelectedQuote property is set fine. If I set this programmatically in my SelectQuote method, it doesn't appear as if the item is selected in the view, although the item is passed back to the MainWindowViewModel and I can use it to populate the textblocks on MainWindow view.
I'd like to be able to show the item on the AllStockQuoteView as being selected via highlighting as if the user selected it.
How can this be done?
Its very easy to implement
You need two things in your view model
A List of your objects and a selected item property
private CustomObject _selectedCustomObject;
public ObservableCollection<CustomObject> CustomObjects
{
get
{
return new ObservableCollection<CustomObject>();
}
}
public CustomObject SelectedCustomObject
{
get { return _selectedCustomObject; }
set
{
if (_selectedCustomObject== value)
{
return;
}
_selectedCustomObject= value;
PropertyChanged.Raise(this, x => x.SelectedCustomObject);
}
}
Then in your view you add your List/Combo control and bind to both properties.
<ListView ItemsSource="{Binding CustomObjects}"
SelectedItem="{Binding SelectedCustomObject}">
Then all you need to do is set the viewmodel properties and the view will update.
First you have to think about your model and the whole MVVM approach, a good starting point is http://blogs.msdn.com/b/kashiffl/archive/2010/11/14/mvvm-technical-description.aspx.
After you can implement your functionality by different ways, one would be to implement something like the Observer Pattern or you try to use methods like Notify Property-Changed-Events.
Hope i was able to help,
Greetings
I have a list box which is binded to a DataView.
<ListBox ItemsSource="{Binding Path=Categories}" DisplayMemberPath="Name"></ListBox>
where Categories is a property to class that inherits the INotifyPropertyChanged interface:
public class EditCategoriesPresenter : INotifyPropertyChanged
{
private DataTable _TableOfCategories;
public DataView Categories { get { return _TableOfCategories.DefaultView; } }
...
}
While all data changes to the underlying DataTable (row inserts and deletes, column value changes) are reflected to list box automatically, when I do a DataTable.RejectChanges() row changes are reflected but not column value changes.
I can understand why this is happening (the DataTable.RejectChanges does not raise any notifications for column value changes) but still cannot find any easy solution to solve it.
I also add the OnPropertyChanged("Categories") after DataTable.RejectChanges() but still no luck.
Any ideas?
Thank you in advance.
when i work with datatables i always use BindingListCollectionView for binding, cause wpf do this anyway implicitly. but now i can use the Refresh() method to refresh my ui binding.
public BindingListCollectionView Categories {get; private set;}
this.Categories = (BindingListCollectionView)CollectionViewSource.GetDefaultView(this._TableOfCategories);
//after reject
this.Categories.Refresh()
nevertheless, what does your ListBox looks like (just the xaml you posted or some datatemplates too)? can you post a screenshot?