I have 2 listviews that serve different purposes. Short question is that I need to find out how to pull specific columns from a WPF listview to add them to properties of an object.
Explanation of what i'm doing:
Listview 1:
Bound to a database table. A user changes a combo box in order to filter the table that the listview is bound to. - I do not need help with this.
Listview 2:
This listview is bound to an observable collection with 3 properties.
- I do not need help with this.
User action:
The user selects a subset of items from Listview 1 and clicks "add". I want to add specific columns of listview 1 to the properties of an "employee" object and then added to an observable collection so they can be displayed in Listview 2.
What I have completed:
The databinding of listview 1 and listview 2 work perfectly. I have an employee class with 3 properties (agent id, name, office). I created an observable collection that I will be adding the employees to - IM FINE with this part.
What I need:
I need to know how to find the specific data of listview 1 in order to assign the correct pieces to the corresponding properties of the objects in my observable collection.
My attempt is really an epic fail.. I will loop through all selected items to get the data from each, but for my try I only used the first selected item:
Class windEmployee
Private Agents As New ObservableCollection(Of Employee)
Private sub AgentData()
Dim x As DataRowView
X = Listview1.SelectedItems(0)
Agents.Add(New Employee With {.AgentID = x.Row.Item(9), .Name = x.Row.Item(6) & " " & x.Row.Item(7), .Office = x.Row.Item(16)}
end sub
End Class
DataRowViewHave you tried just itterating through the SelectedItems?
foreach (DataRowView row in Listview1.SelectedItems)
{
...
}
Related
I have a usercontrol, with one list box and one list view control in it. For Listview i have bound the observablecollection of type TrafficManager class as shown below:
private static ObservableCollection<TrafficManager> _trafficCollection;
public ObservableCollection<TrafficManager> TrafficCollection
{
get { return _trafficCollection; }
set
{
_trafficCollection = value;
OnPropertyChanged("TrafficCollection");
}
}
I have bound this to itemsource of list view.
Now my requirement is on selection of the listbox item, i need to filter some items of the listview. For that i used a linq to get the desired rows from list view and added that to the list view collection. Before adding i did a listview Collection TrafficCollection.Clear() and then added to that collection.But now the issue is on selection of another item in list box i need the original listview contents again to carry out the filtering using the linq again. Here once the TrafficCollection.Clear() executes the original observable collection data vanishes. How do i maintain a backup of original observable collection data "TrafficCollection" of listview. Remember i have only one view. Is there anyway to do this? Please let me know.
you can use CollectionViewSource filtering, refer here
SO Link: Trigger Filter on CollectionViewSource
this will not clear original collection.
In my form I have a DataGridView bound to a BindingSource that has a DataSet as DataSource. I also have some TextFields and ComboBoxes on the form that are bound to different columns in the DataSet through the BindingSource. The idea is that the values in the columns on the selected row in the DataGridView are reflected in the other controls on the form. Maybe I make it sound a bit complicated, but it's fairly easy to connect the TextFields, and also the ComboBoxes bound to tables in the dataset.
My problem is that this time I want to set the items in the ComboBox from an array and not from a table in the DataSet. This is what I've tried:
Me.ComboBox.DataBindings.Add(New System.Windows.Forms.Binding("SelectedValue", Me.TblBindingSource, "ColumnName", True))
Dim ItemArray(2) As String
ItemArray(0) = ""
ItemArray(1) = "Default"
ItemArray(2) = "User-set"
ComboBox.DataSource = ItemArray
Now, this seems to work partially as the ComboBox is populated correctly, and I can select a value, and it appears in the DataGridView. But it doesn't update its selected value as I change rows in the DataGridView. The column ("ColumnName") is a ComboBoxColumn that gets its item list in the way shown above, and it seams to work as expected.
If it wasn't clear; I have several ComboBoxes with similar functionality that works, but they are bound to a column in a DataTable, as follows:
Me.ComboBox1.DataBindings.Add(New System.Windows.Forms.Binding("SelectedValue", Me.Tbl1BindingSource, "WiDMethodX", True))
Me.ComboBox1.DataSource = Me.Tbl2BindingSource
Me.ComboBox1.DisplayMember = "SomeColumn"
Me.ComboBox1.ValueMember = "SomeColumn"
If it matters, the DataSet comes from an Access Database.
SelectedValue is used in conjunction with the ValueMember property, but since your array list doesn't have descriptive fields, that won't work.
Try using SelectedItem for your binding:
Me.ComboBox.DataBindings.Add(New Binding("SelectedItem", _
Me.TblBindingSource, "ColumnName", True))
I realize this questions is old, but I had similar problem I resolved. I bound the text property of the combo box to the binding source member that relates to the value member or display member of my combo box datasource. Make sure that you fill your data tables (for binding source and combo box datasource) AND bind your combo box to its datasource prior to databinding text of combo box.
Dim dtForBindingSource as DataTable
Dim bs as BindingSource
Dim dtForComboBox as DataTable
'Code to fill dtForBindingSource would go here
bs.DataSource = dtForBindingSource
'Code to fill dtForComboBox would go here
ComboBox.DataSource = dtForComboBox
ComboBox.DisplayMember = "ColumnToDisplay"
ComboBox.ValueMember = "ColumnXYZ"
'Now that datasources exist and combo box is set up I do databindings.
ComboBox.DataBindings.Add("Text", bs, "ColumnToDisplay")
My issue goes like that:
I have 2 ListBox:
one is bound to a collection called photos of type Photos and the other is bound to a CollectionViewSource which is bound to the same photos collection.
listBox1 -> photos (here the listBox1 is bound to the Default CollectionView of photos, of course and not directly to photos.)
ListBox2 -> cvs -> photos
both collection (the default one and my CVS) having a filter that reduce the items they show from 8 items to 5 items.
now i have 2 labels. one is bound to the Count property of the photos object and the other one is bound to the Count property where the source is the cvs (my CollectionViewSource) object.
the first label show the number 8 and as i see it, it is because the Count of photos stays 8 even though i am filterring it's default CollectionViewSource.
the second label shows the number 5.
what i learnt about binding to a cvs is that WPF unwrapps the source object from the cvs and the Path=Count is relevant to the underlying object which is photos and the number here should be 8 also.
does someone can explain me where i am worng?
thanks!
The binding will not bind to the source collection but the view. The collection view also has a Count property which returns the number of items in the (filtered) view rather than in the original collection.
(You can use the debugger to see that the View property of the CollectionViewSource normally will be an object which is an instance of CollectionView or one of its subclasses. The binding will implicitly bind to View.Count)
To bind to the original count use the path SourceCollection.Count.
I have a ObservableCollection , where MyData is a class with 4 properties i.e. int id, string name, bool IsSelected, string IsVisible.
This ObservableCollection is binded to a combobox with checkboxes(Cities data for example). Now, when the user checks the checkboxes then next time when he opens the drop down - all selections should come on top in ascending order by name.
I have also implemented auto complete when the user types in 3 chars in the combobox, the drop down will open showing all the selections first, then then all the items starting from the 3 chars type in by the user.
I have researched and implemented the following code and it is working fine, but i want to know whether this is the best approach or can i implement this in a better manner, code is :
IEnumerable<MyData> sort;
ObservableCollection<MyData> tempSortedCities = new ObservableCollection<MyData>();
sort = City.OrderByDescending(item => item.IsSelected).ThenBy(item => item.Name.ToUpper()) ;
// City is my observablecollection<MyData> property in my Model binded to combobox in UI
foreach (var item in sort)
tempSortedCities.Add(item);
City.Clear(); // City is my observablecollection<MyData> property in my Model
City = tempSortedCities;
tempSortedCities = null;
sort = null;
Thanks in advance for your time !
ICollectionView seems to be a perfect fit for this. It was designed specifically for sorting, filtering and grouping of a collection without modifying the original collection.
You can get an instance of ICollectionView for your collection using the following code:
var sortedCities = CollectionViewSource.GetDefaultView(City);
Then you can setup sorting by adding instances of SortDescription type to the ICollectionView.SortDescriptions collection:
sortedCities.SortDescriptions.Add(new SortDescription("IsSelected", ListSortDirection.Descending));
sortedCities.SortDescriptions.Add(new SortDescription("Name", ListSortDirection.Ascending));
Then you can bind your ComboBox directly to the collection view (instead of City collection) and it will display already sorted data.
I've created a dataset that contains 2 tables:
Users (userID, UserName, other user details)
Emails (Id, UserId, UserEmail)
I populate the dataset using 2 DataAdapters (one for each table)
I have a listbox, a few textboxes and a grid.
listbox gets all the users, the few textboxs displays the user details when picked in the list box (this is easy b/c they are both bound to the same table).
the grid should display the selected user's email addresses.
How do I do it using binding ? is it possible or should I catch the selection change event and filter the grid "manually" (currently the grid displays all the emails in the tables).
If you have a collection that contains all the emails, then you could try looking at making the ItemsSource of your grid an object that implements the ICollectionView interface - this allows you to filter, sort and group your collection...
You can get an object that implements this interface by calling
var view = CollectionViewSource.GetDefaultView(myList);
You can have a property called SelectedUser and bind it to the SelectedItem of ListBox. In the setter of the property you can filter the email list that is bound to grid.
But in the long run, you can create models out of your tables using some ORM tools or Linq-to-sql available in VS which will create models and their relationship. Hence when you will have something like this
Class User
{
UserId, UserName, List<Email> that user has
}
You can create a List<User> and a SelectedUser property which would be bound to the UI elements.
The grid would be bound to SelectedUser.Emails Hence everything is bound and the flow would work fine.