ListBox, DataView, And DataTable.RejectChanges() - c#

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?

Related

How can I set the collection object in database table using SQlite?

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.

DataGridView not updateing when I'm changing datasource

I have DataGridView and DataSource is List. When I'm changing elements property in that List in gridview it is shown previous. When I click on row it changes values. I'm updating list with BackgroundWorker. How update DataGridView at the same time?
You will have to use ObservableCollection combined with INotifyPropertyChanged as ObservableCollection notifies only when items are added or removed but not when they are changed.
ObservableCollection Class
How to Listen to Property Changes of Items of an ObservableCollection
There is also one more similar question on SO that might help you.
modified excerpt from msdn
private void RefreshGrid(object dataSource)
{
yourGridName.Invoke((Action)delegate
{
var myCurrencyManager = (CurrencyManager)yourGridName.BindingContext[dataSource];
myCurrencyManager.Refresh();
});
}
Call this method whenever your background worker updates the dataSource.

Changing complete lists of content in Combo Boxes

In my program I have a comboBox and a listBox. The listBox is full of different commands. The selectedItem and contents of the comboBox depend on which command is selected. The selectedItem in the comboBox stays selected for that command. For example, when the user has content selected in the comboBox and they switch to a different command, and then switch back, the same item will still be selected in the comboBox.
Because the comboBox gets populated with different items depending on which command is selected should I make an ObservableCollection for each set of items? I'm only allowed to bind the ItemsSource to one thing, so how would that work?
If that's not the right approach please advise. If this isn't clear enough, please let me know.
Thanks!
Here's a sample of what my program will look like:
Then, if command 2 is selected, the list in the combo box might be a, b, c, d, e, for example.
You can have a separate ObservableCollection for each listbox command.
When the user selects a new listbox command, set the comboBox.ItemsSource to the appropriate ObservableCollection. That should solve your problem.
Based on your description, the contents of the combobox are tied to the selected item in the listbox. Without knowing any more of the details, seems like your business object would be a “Command” object that contains an ObservableCollection of “SubCommand”? objects. Your application would then contain an Observablecollection of “Command” objects. The listbox would be data bound to the "Command" objects list, and the combobox would be bound to the selected items "SubCommand" collection.
Seems to me you're looking for a Master / Detail structure here:
Data Items:
public class MyCommandDefinition
{
public string DisplayName {get;set;}
public List<MyParameter> Parameters {get;set;}
public Parameter SelectedParameter {get;set;}
}
public class MyParameter
{
public string DisplayName {get;set;}
//Additional properties depending on your needs.
}
ViewModel:
public class MyViewModel
{
public List<MyCommandDefinition> Commands {get;set;}
public MyCommandDefinition SelectedCommand {get;set;}
}
XAML:
<ListBox ItemsSource="{Binding Commands"}"
SelectedItem="{Binding SelectedCommand}"
DisplayMemberPath="DisplayName"/>
<ComboBox ItemsSource="{Binding SelectedCommand.Parameters}"
SelectedItem="{Binding SelectedCommand.SelectedParameter}"
DisplayMemberPath="DisplayName"/>
Don't forget NotifyPropertyChanged() in all these properties if you're going to change them programatically and expect that to be reflected in the UI.

Binding DataGridView with IList<T>, edit and then save only the changes?

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.

How can I programatically select a listview item from within the viewmodel?

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

Categories