After a user clicks on any number of items in a CheckedListBox, I want to programmatically remove the checks on those items when the window is closed. With the CheckedListBox named lstChoices, I have:
For I As Integer = 0 To lstChoices.SelectedItems.Count - 1
Dim lbi As Xceed.Wpf.Toolkit.Primitives.SelectorItem = CType(lstChoices.ItemContainerGenerator.ContainerFromIndex(I), Xceed.Wpf.Toolkit.Primitives.SelectorItem)
lbi.IsSelected = False
Next
The problem is that the SelectedItems property is NOT the selected items. Oddly, the SelectedItems.Count property is computed correctly but the loop just goes through the first ListBoxItems up to Count whether they are selected or not.
The documentation says the SelectedItems property "Gets the collection of checked items". Either the documentation is wrong or there's a bug in that control. How can I get just the checked items.
You are currently iterating over the Items collection as ContainerFromIndex returns an item based on the Items property and not the SelectedItems property.
You should iterate the SelectedItems and use lstChoices.ItemContainerGenerator.ContainerFromItem instead:
For index As Integer = 0 To lstChoices.SelectedItems - 1
Dim selectedItem = lstChoices.SelectedItems(index)
Dim selectedItemContainer = TryCast(lstChoices.ItemContainerGenerator.ContainerFromItem(selectedItem), Selector)
selectedItemContainer.IsSelected = False
Next
You have to be careful to make the difference between the elements of SelectedItems and Items.
Try this :
For I As Integer = 0 To lstchoices.SelectedItems.Count - 1
lstchoices.SetItemCheckState(lstchoices.Items.IndexOf(lstchoices.SelectedItems(I)), CheckState.Unchecked)
Next
Related
I have subclassed the WPF DataGrid in my VB.NET application because I will need to use this component frequently but also need to have some extra features, in this case adding a new row when the tab key is pressed on the bottom right cell.
I have Overidden the OnKeyDown event of the base class. This is being triggered when the tab keys is pressed while the grid is focused, exactly as I want. However, when the event is triggered I need to be able to determine whether I'm on the bottom-right cell or not. To do this I'd like to get the SelectedItem property of my DataGrid and use that to determine which cell is selected.
I am doing all of this programmatically because I don't want users to have to write any more XAML than they would have to for a regular datagrid. It should function in exactly the same way except if you tab on the bottom right cell a new row is added and the first cell of that row is selected. this should apply no matter how many rows/columns the user has in the datagrid.
The code below shows what I want to do but the SelectedItem is not set.
Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
MyBase.OnKeyDown(e)
If e.Key = Key.Tab Then
Dim colIndex As Integer = Me.Columns.IndexOf(Me.CurrentColumn)
Dim colCount As Integer = Me.Columns.Count - 1
If -1 = colIndex Then
'the next line throws a System.NullReferenceException because SelectedItem is not set
If SelectedItem.Equals(Items(Items.Count - 1)) Then
Focus()
Dim dgrCI = New DataGridCellInfo(Items(Items.Count - 1), Columns(colIndex))
ScrollIntoView(Items(Items.Count - 1))
BeginEdit()
End If
End If
End If
End Sub
The SelectedItem property should be set to the last item in the table but is instead set to Nothing. Why is this?
Edit:
The answer from Ppp is correct. it seems that by the time the OnKeydown event is triggered the DataGrid has already lost focus. I resolved this issue by using the OnPreviewKeydown event instead.
When your tab key is pressed in the last cell you basically tab out of the datagrid which is why I am guessing your SelectedItem is null.
I have a WPF DataGrid, and the DG's ItemsSource is set when the user selects a Dictionary from a bunch of options.
I added a column of CheckBoxes to the DG and set it up so that only 1 row can have IsChecked = true at a time. When the user "checks" one of the boxes, the Checked event handler cycles through all the rows and sets IsChecked = false to each row's CheckBox except the SelectedItem, leaving only the row the user selected as IsChecked = true. This works fine when a CheckBox is Checked by the user.
But this CheckBox column is not "bound" to any piece of data in the Dictionary. So when the user "selects" which Dictionary to bind the DG to, the "default" object in that Dictionary is not marked as "default." So I try to .IsChecked = true the correct row directly after the ItemsSource is set.
BUT the problem lies in the fact that my Checked event handler IsChecked = falses everything but the SelectedItem, and then checks the SelectedItem.
When the user initially chooses which Dictionary to bind to the DG, the DG is filled (and checked) programmatically. THEREFOR the SelectedItem is always the first row. So, instead of IsChecked = trueing the ACTUAL default object, the DG IsChecked = trues the first row.
THE CLOSEST I GOT TO A SOLUTION:
I tried to modify the Checked event handler so that instead of getting the SelectedItem, it figures out which row is the "default" row, "unselects" all other rows, and ONLY "selects" this row. But for some reason this call doesn't work.
dataGridSymbols.UnselectAll()
dataGridSymbols.SelectedItem = row
Does anybody know what's wrong with this call? I know that I set the row correctly.. Maybe I need to set SelectedItem to the object, but how to I get to the object from the row?
I figured this out. Instead of using SelectedItem (which just returns whichever is highlighted) I finally found a way to use the row that the Checked event handler was called from. Here's the code that solved it, in case anybody wants to see.
var cell = sender as DataGridCell;
if (cell == null)
return;
// Keep getting parents until you get to the sender's row...
var parent = VisualTreeHelper.GetParent(cell);
while (parent != null && parent.GetType() != typeof(DataGridRow))
{
parent = VisualTreeHelper.GetParent(parent);
}
var row = parent as DataGridRow;
if (row == null)
return;
var rowIndex = row.GetIndex();
I'm using ObservableCollection to bind data into list box. Is there a way to make first list item to be selected right after data binding? Is there any event I can use ?
Thank you
Right after (or any point after) setting the datacontext for the listbox (or parent object - probably the page), just set the selected index to the first item in the list.
listbox.SelectedIndex = 0;
If you've got a handler for when the selected index is changed then be sure to ignore when you first set the index.
Create a property named IsSelected in the object contained within the ObservableCollection. Bind this to the ListBoxItem's IsSelected property via a TwoWay binding.
Then, in the page's OnLoaded callback (or wherever you're binding the collection to the ListBox), do something like this
foreach( var obj in myCollection ) {
obj.IsSelected = false;
}
if( myCollection.Count > 0 ) {
myCollection[0].IsSelected = true;
}
// bind the collection to the listbox
why won't you try something like
var listBoxItem = ItemContainerGenerator.ContainerFromItem(myList.First());
listBoxItem.Focus();
or
listBoxItem.IsSelected = true;
I m working with WPF DataGrid and I want to retrieve a DataGridCell's value by using the column and the row indexes : all what I could do is this but it didn't work :
myDatGrid.Columns[0].GetCellContent((DataGridRow)myDatGrid.Items[0]);
Could you please show me the way to realize that
Your cells value is going to be contingent on what the given column is bound to. The entire row will be the instance of your model.
Assume we have a collection of Person classes which we are binding to within our DataGrid.
Person p = ((ContentPresenter)myDatGrid.Columns[0].GetCellContent(myDatGrid.Items[0])).Content;
The Content property is going to return the underlying model for the row. If you wanted to obtain a given property you can do so by directly accessing the underyling object which should implement INotifyPropertyChanged, no need to fool with the DataGrid as you would in a WinForms application.
I tried what has been proposed above and it did not work.
I struggled for a whole day trying to bind a ComboBox and select the correct value in a WPF Datagrid when it first loads, so I thought I would share my solution here in hopes that somebody else could benefit. Sorry about the VB, but the concept should work in C# also.
First, if you are trying to get the values populated and selected when the grid first loads, you need to put your code in the correct event handler: LayoutUpdated. In other event handlers, the GetCellContent function returns Nothing (null). You could also put this code in an event handler which handles an event occurring later, such as a Button.Click event, if that meets your requirements.
Second, the code:
For i As Int32 = 0 To DataGrid1.Items.Count - 1
Dim row As DataGridRow
row = DataGrid1.ItemContainerGenerator.ContainerFromItem(DataGrid1.Items(i))
If row IsNot Nothing AndAlso row.Item IsNot Nothing Then
Dim cp As ContentPresenter = DataGrid1.Columns(3).GetCellContent(DataGrid1.Items(i))
If cp IsNot Nothing AndAlso cp.ContentTemplate IsNot Nothing Then
Dim dt As DataTemplate = cp.ContentTemplate
If dt IsNot Nothing Then
Dim cb As ComboBox = dt.FindName("cbVendorNames", cp)
If cb IsNot Nothing Then
cb.ItemsSource = Vendors
cb.DisplayMemberPath = "VendorName"
cb.SelectedValuePath = "AS_ID"
cb.SelectedValue = "" ' set your selected value here
End If
End If
End If
End If
Next
What this code does is (a) loop through all of the rows in the datagrid, (b) get the ContentPresenter for the cell selected (in this case, cell 3 in each row), (c) get the DataTemplate for the ContentPresenter, and (d) finally, get the reference to the ComboBox. This allowed me to bind the ComboBox to an external datasource (a List(Of Vendor) and select its value. This code worked for me.
I do not find this solution particularly elegant or efficient, but it does work. If somebody has a better solution, please post it.
OK I think I got it , I missed some casts that I should put , because the column I'm using is a DataGridComboBoxColumn
I should actually do this :
((ComboBox)(myDatGrid.Columns[0].GetCellContent(
(TestData)myDatGrid.Items[0]))).SelectedValue.ToString());
Now it works.
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)
{
...
}