Databinding bindinglist to combobox and removing items - winforms

I am trying to use windows forms databinding to hook up a combobox to a ViewModel class.
var items = new BindingList<Person>();
comboBox.DataSource = items;
comboBox.DisplayMember = "Name";
All works ok except when I remove items from the list. For example if I remove the currently selected item (selected in the combobox) the selectedIndexChanged and SelectedValueChanged events of the combobox don't fire.

Found an answer. I had to use a BindingSource as middleman
var bindingsSource = new BindingSource();
bindingsSource.DataSource = new BindingList<Person>();
comboBox1.DataSource = bindingsSource;
comboBox1.DisplayMember = "Name";
This way I do get value changed events and even more than one when I deleted something.

Related

TextBox inside a listview cell

I have a listview that I would like to add a textbox inside each gridview column cell so I can type data into it and then fetch that data.
I'm creating a datatemplate and passing it to a cell template for the GridViewColumn but when I look at the listview I can't add anything to the cell. It doesn't look like the textbox was even created.
GridViewColumn conceptColumn = new GridViewColumn();
conceptColumn.Header = conceptName;
conceptColumn.CellTemplate = this.GetDataTemplate();
this.TestModeler.Columns.Add(conceptColumn);
conceptColumn.DisplayMemberBinding = new Binding(conceptName);
private DataTemplate GetDataTemplate()
{
DataTemplate dt = new DataTemplate(typeof(TextBox));
FrameworkElementFactory txtElement = new FrameworkElementFactory(typeof(TextBox));
dt.VisualTree = txtElement;
Binding bind = new Binding();
bind.Path = new PropertyPath("Text");
bind.Mode = BindingMode.TwoWay;
txtElement.SetBinding(TextBox.TextProperty, bind);
txtElement.SetValue(TextBox.TextProperty, "test");
return dt;
}
Please take a look at the ListView Class page at MSDN where you can find a XAML example and plenty of link on how to do various things with a WPF ListView.
Of particular interest to you, please take a look at the How to: Use Templates to Style a ListView That Uses GridView page there which explains what you are trying to do (but in XAML) with examples.
MSDN should always be your first place to look as it is full of information just waiting to be read.

Can databinding in WPF be done simply with a dataview like in winforms?

Short and simple question. In Winforms you can bind a dataview to a combobox or some other control by simply:
combobox.DataSource = dataview
combobox.DisplayMember = "Something"
In WPF I've generally done databinding using an ObservableCollection and edits to the xaml. Is there a way to quickly do it, like the above?
Edit:
This seems to be the simplest/quickest thing I can come up with, anything inherently wrong with it?
combobox.ItemSource = dataview
combobox.DisplayMemberPath = "Something"
You can set binding programmatically, although, per my understanding of the MVVM pattern, the best practice is to set binding in the View (xaml) not the ViewModel or View code-behind.
How to set binding programmatically:
Binding myBinding = new Binding("Name");
myBinding.Source = dataview // data source from your example
combobox.DisplayMemberPath = "Something"
combobox.SetBinding(ComboBox.ItemsSourceProperty, myBinding);
With this, when your dataview is updated, the updates will be shown in your ComboBox.
You can do this:
List<Person> someListOFPersons = new List<Person>();
comboBox.DataContext = someListOfPersons;
comboBox.DisplayMemberPath = "FirstName";
You will not see changes in the collection. So if a person is added to or removed from the list the combobox will not see it.

this.Teams = new ObservableCollection<TeamViewModel>(_teams);

I'm new to mvvm and I can't seem to find the answer to the following:
I have a datagrid in Silverlight which binds to a observablecollection Teams of a viewmodel:
First I fetch a couple of team objects in a List and then I feed them to my observablecollection
(Public ObservableCollection Teams)
Now I want to add a row in the Datagrid so I created a button in the view and hooked up an Icommand which adds more or less an empty team to my collection:
private void Add()
{
Team _team = new Team();
_team.recid = 1;
_team.teamid = "";
_team.ruleset = "";
_team.name = "";
this.Teams.Add(new TeamViewModel(_team));
}
I think the notifypropertychanged doesn't fire (only when I set the collection), what do I have to do to notify the view of my changed viewmodel?
Thanks in advance,
Michael
Adding to an ObservableCollection does not raise PropertyChanged, but instead raises a collectionchanged event.
The easiest way is to manually RaisePropertyChanged for the Team property at the end of your add function.
If you databound your Teams property (which is of the type ObservableCollection), your Grid should automatically update.
There's no reason to call RaisePropertyChanged("Teams") when adding or removing items from a ObservableCollection.
So in short, it should already work. If it doesn't, you need to post more code.
I guess it didn't show up in the grid because I added empty strings for teamid / name. When I do it like this the row is visible in the grid: _team.recid = 1; _team.teamid = "test"; _team.ruleset = "test"; _team.name = "test"; _team.rowstate = GlobalVariables.Rowstate.added; Thanks Claus / Brandorf for your comments!
Regards, Mike

WPF datagrid empty row at bottom

I bind my datagrid using
//fill datagrid
public DataTable GameData
{
get
{
DataSet ds = new DataSet();
FileStream fs = new FileStream(IMDB.WebPage.Class.Config.XMLPath,
FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(fs, Encoding.Default);
ds.ReadXml(reader);
fs.Close();
DataTable temp = ds.Tables[0];
return ds.Tables[0];
}
}
For some reason I get an empty row at the bottom. And sometimes after clicking on some buttons and checkboxes in the grid, more empty rows are added.
Why is this? And how do I block this?
Sounds like you probably have CanUserAddRows set to true for the DataGrid. Just add
CanUserAddRows="false"
to the XAML.
It also works with the attribute:
IsReadOnly="true"
If your backing collection that implements IEditableCollectionView returns true from its CanAddNew method, the DataGrid will assume that is what you want to do.
There's a good overview here:Overview of the editing features in the WPF DataGrid
If you're creating DataGrid on-the-fly through Source Code...
DataGrid grid = new DataGrid();
grid.CanUserAddRows = false;
//...
grid.AutoGenerateColumns = false;
grid.Margin = new Thickness(10,20,10,10);
grid.VerticalAlignment = VerticalAlignment.Top;
grid.ItemsSource = //... and so on
Though the OP was asking how to REMOVE the empty row, the title isn't specific, and this article appeared in my search while trying to figure out how to ADD the empty row. I found that, for the empty row to appear, it not only needs to have CanUserAddRows="True" but the ItemsSource needs to have a default constructor public MyClass () { }.

WPF binding not notifying of changes

I have a WPF sorting/binding issue. (Disclaimer: I am very new to WPF and databinding so apologise if I am asking a really dumb question :-))
Firstly, I have a linqToSql entity class Contact with an EntitySet<Booking> property Bookings on it.
If I directly bind this Bookings property to a ListView, the application seems to correctly notify of changes to the selected item in the ListView, such that a textbox with {Binding Path=Bookings/Comments} updates correctly.
// This code works, but Bookings is unsorted
var binding = new Binding();
binding.Source = contact.Bookings;
bookings.SetBinding(ItemsControl.ItemsSourceProperty, binding);
However, as I can't seem to be able to find a way to sort an EntitySet (see this post), I am trying to bind instead to an Observable collection, e.g:
// This code doesn't notify of selected item changes in the ListView
var binding = new Binding();
binding.Source = new ObservableCollection<Booking>(contact.Bookings.OrderByDescending(b => b.TravelDate).ToList());
bookings.SetBinding(ItemsControl.ItemsSourceProperty, binding);
But this doesn't seem to notify the comments textbox correctly such that it updates.
If anyone has a solution for either sorting the data before or after its bound, or another solution that will work that would be much appreciated.
You should bind to a CollectionView rather than the collection itself. That will allow you to specify whatever sorting criteria you require. Example:
var collectionView = new ListCollectionView(contact.Bookings);
collectionView.SortDescriptions.Add(new SortDescription("TravelDate", ListSortDirection.Ascending));
var binding = new Binding();
binding.Source = collectionView;
bookings.SetBinding(ItemsControl.ItemsSourceProperty, binding);
Hainesy,
Does the Booking object implement INotifyPropertyChanged to notify change in Comments property?
If not, you cannot expect TextBox which is bound to Comments property to be updated automatically when Comments change
Using ObservableCollection in this case will only get you the benefit of updating the view with changes when Booking objects are added or deleted from the collection
-Rajesh

Resources