how to prevent autoselection of first item in GridView on databind? - c#

When I databind my GridView to an ObservableCollection, the first item of the collection is automatically selected. The SelectionMode property of the GridView is set to multiple. Is there some way to prevent this auto-selection? Or on what event should I listen so that I can reset the SelectedIndex of the GridView back to -1?

Set the IsSynchronizedWithCurrenItem property to false on the gridview in xaml

There is acutally a pretty simple solution. I set the SelectionMode of the GridView to None in the XAML. Then, when the page is created, I change the SelectionMode to Multiple.
publicPage()
{
this.InitializeComponent();
itemListView.SelectionMode = ListViewSelectionMode.Multiple;
}
However, the problem I am having seems to be caused by my own program. This is a workaround for the issue I am having, the autoselection is not the default behavior.
http://social.msdn.microsoft.com/Forums/en-US/winappswithcsharp/thread/da7e9f3b-9a3e-47ca-8223-b50539293f5f

My situation is the opposite. I have a GridView that was bind to an ObservableCollection, and I wanted the 1st item to be selected but it was not! I figured out why that was the case though. There are 2 ways to generate my ObservableCollection and depending on which method I chose, the 1st item is either selected or not.
for example, I have a variable ItemList in my viewmodel which I bind to my GridView
public ObservableCollection<Item> ItemList { get; private set; }
Method 1 (nothing selected)
public void getData()
{
var myList = // get your list here
for (int i = 0; i < myList.Count; i++)
{
this.ItemList.add(myList[i]);
}
}
Method 2 (1st item automatically selected)
public void getData()
{
var myList = // get your list here
this.ItemList = myList
}

Related

Updating a Databound GridView with changes

I have a DataGridView on a form that is databound to a list of objects. I have several column including a checkbox column. The requirement is that only one item in the collection may have the databound boolean property set to true at a given time. The data object is named Interval, the Property in question is Program:
public bool Program
{
get { return _program; }
set
{
if (value)
{
Parent.Intervals.Except(new[] { this }).ForEach(interval => interval.Program = false);
}
_program = value;
OnPropertyChanged();
}
}
My expected behavior would be that clicking the databound checkbox would set the Program property for one instance of Interval to true, and in so doing, would set the Program property on all other instances to false. That is indeed what happens, however the datagridview does not update correctly. It will leave previous checkboxes checked and after tabbing off the cell or mousing over another checkbox, then it will update that particular checkbox.
How can I get the datagrid view to accurately show the state of my objects. I trusted you, DataGridView! You lied to me. I... I can never trust anything you say again.
The solution is to use a BindingList instead. When binding to a regular List or other collection (that is not of a Binding specific bent), only the selected rows values are updated. BindingList, however, has the added benefit that properties from all of the items are updated, not just the selected Row. Keep in mind that if you are using something like AddRange (from List) you may have to modify your code to add items either at initialization time or via a loop, as BindingList does not have an AddRange method (although an extension method could be written).
Try this
private void dgv_CellValueChanged(object sender, DataGridViewCellEventArgs e)
{
if ((bool)dg.Rows[e.RowIndex].Cells[CheckBoxColumnIndex].Value)
{
var rows = (from DataGridViewRow row in Clients.Rows
where row.Index != e.RowIndex
select row).ToArray();
foreach(DataGridViewRow row in rows)
{
row.Cells[CheckBoxColumnIndex].Value = false;
}
}
}

DataGrid NewItemPlaceholderPosition lost when ItemsSource changed

I have two DataGrids above one another, and selecting a row in the top grid, OrdersGrid, displays some details in the bottom grid, DetailsGrid, about the selected row from OrdersGrid.
I would like the NewItemPlaceholderPosition to be AtBeginning for both grids. This is easy enough for OrdersGrid because I can just set it in my UserControl subclass constructor:
((IEditableCollectionView)OrdersGrid.Items).NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtBeginning;
But the problem is that the ItemsSource for DetailsGrid is a member of the currently selected item in OrdersGrid.
If I set NewItemPlaceholderPosition for DetailsGrid as above then it works until I click on a new row in OrdersGrid when it goes back to the default of being at the bottom since DetailsGrid reloads from its new ItemsSource.
The ItemsSource for OrdersGrid is an ObservableCollection called Orders, which contains Objects of type Order, and the ItemsSource for DetailsGrid is Order.Details, also an ObservableCollection, for the current Order.
I'm thinking I want something like an ItemsSourceChanged event for DetailsGrid, but I'm not sure if this is the correct approach or even how to go about this. Please help!
I was able to solve this problem by adding the following to my UserControl subclass constructor:
((IEditableCollectionView)DetailsGrid.Items).NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtBeginning;
var dpd = DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty, typeof(DataGrid));
if (dpd != null)
{
dpd.AddValueChanged(DetailsGrid, DetailsSourceChanged);
}
with the DetailsSourceChanged method defined as followed:
private void DetailsSourceChanged(object sender, EventArgs e)
{
if (DetailsGrid.Items.Count > 0)
{
((IEditableCollectionView)DetailsGrid.Items).NewItemPlaceholderPosition = NewItemPlaceholderPosition.AtBeginning;
}
}

Add item to binded combobox to list

I have a combobox binded to a list like this
public List<CustomerLanguage> CurrentCustomerLanguageList
{
get { return _currentCustomerLanguageList; }
set
{
_currentCustomerLanguageList = value;
bsCustomerLanguages.DataSource = Presenter.CustomerLanguageToProxy(value);
cbLanguage.DataSource = bsCustomerLanguages.DataSource;
cbLanguage.DisplayMember = "LanguageName";
cbLanguage.ValueMember = "Id";
}
}
On the form i have + - buttons which must allow to add or delete items inside combobox.
The problem is: i dont know how to add new item to binding source and the list without full refresh of combobox.
Of course when i add, selected value must remains and no selectedvaluechanged event must be raised.
'bsCustomerLanguages' is a BindingSource ? In that case it should work if you set cbLanguage.DataSource = bsCustomerLanguages and add to bsCustomerLanguages directly

ComboBox SelectedIndex MVVM WPF

I have a ComboBox bound to an ObservableCollection of tbPublications which populates as it should. I then select a row from a DataGrid which fires another Create form in which I insert a new record into tbPublications, all good.
When I close said create form and return to my ComboBox form I am clearing and re-reading in the one new item to my ObservableCollection, returning the user to the item they've just created. The ComboBox then displays the one item from my newly populated collection, all good.
My problem is that on returning to my ComboBox form, the new publication is not set as selected item in the ComboBox display, the user has to click the ComboBox then select the item.
I can't use SelectedIndex = "0" in my view XAML as I want to show the whole ObservableCollection in my ComboBox on page load.
Is there any way to use a method in the ViewModel maybe to solve this issue, something maybe such as..
private void SetSelectedIndex()
{
if (MyObservableCollection.Count == 1)
{
//Set selected indexer to "0";
}
}
Found a solution to this, not sure if it's the cleanest 'MVVM' solution...
After reading in my ObservableCollection I invoke this method:
if (_ModelPublicationsObservableList.Count == 1)
{
SelectedPublication = _ModelPublication;
SetSelectedIndex();
}
Here's the method which gets the current main window and sets the SelectedIndex:
private void SetSelectedIndex()
{
ArticlesDataGridWindow singleOrDefault = (ComboBoxWindow)Application.Current.Windows.OfType<ComboBoxWindow>().SingleOrDefault(x => x.IsLoaded);
singleOrDefault.comboBox1.SelectedIndex = 0;
}
Did you consider using the SelectedItem property of combobox? You can bind the selected item property of combobox to get or set the selected item.
XAML
<ComboBox ItemsSource="{Binding Path=Publications}" SelectedItem="{Binding Path=SelectedPublication, Mode=TwoWay}" />
ViewModel
public class ItemListViewModel
{
public ObservableCollection<Publication> Publications {get; set;}
private Publication _selectedPublication;
public Publication SelectedPublication
{
get { return _selectedPublication; }
set
{
if (_selectedPublication== value) return;
_selectedPublication= value;
RaisePropertyChanged("SelectedPublication");
}
}
}
If you want to set the selected item from View model,You can set the SelectedPublication property as-
SelectedPublication = Publications[0];
Or you can locate the required item in the Publications collection and assign it to SelectedPublication property.
Add UpdateSourceTrigger=PropertyChanged to your binding.
SelectedItem={Binding Path=SelectedPublication, Mode=TwoWay}, UpdateSourceTrigger=PropertyChanged}

Automatically set SelectedIndex on ComboBox when populated

By doing either an Items.Add() or Items.AddRange() call, is there a way to automatically set SelectedIndex to 0 if it is set to -1?
My first guess would be to create a new event that listens to a change in the Items property.
If you are not willing to set SelectedIndex = 0 after the Add (which I personally do not think is too tedious...but to each their own), then you could try creating a custom control that will do this for you. However, there is no event for when an item is added, so you would have to create a new method.
public class MyComboBox: ComboBox
{
public void AddItem(object item)
{
base.Items.Add(item);
if (SelectedIndex == -1)
SelectedIndex = 0;
}
}
Ultimately, this seems like a bit of overkill, but it is doable this way.

Categories