ComboBox SelectedIndex MVVM WPF - c#

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}

Related

C# MVVM - how doI prevent duplicated content in a multiple combobox selection?

I have five ComboBoxs which are using the same enum content.
Each ComboBox should not have the same value.
If box one has selected content "beef", box two has selected the content "beer".
And now I select "beer" in box one, and both contents should switch. I'm actually using a method with checks both with if and else (working, but really boring).
Is there a smarter solution?
For each box I have one of this trigger and Model.BoxOneValue, Model.BoxTwoValue...
private void OnBoxOneChange(PropertyChangedEventArgs e)
{
}
Can't post a full answer without that xaml but if you can pass it a ComboBox via CommandParameter
public RelayCommand<object> BoxChangeCommand { get { return new RelayCommand<object>(OnBoxChange); } }
private void OnBoxChange(Object comboBox)
{
ComboBox list = comboBox as ComboBox;
if (list != null) {
//do stuff
var items = list.Items;
var selectedItem = list.SelectedItem;
}
}
you'll need using System.Windows.Controls for the ComboBox
There is another way too, by binding your SelectedItem in the xaml to your VM and you can press a button on the frontend and the VM with figure everything out.

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

WPF Can't Select Items in Datagrid after adding it to the ObservableCollection

I have a datagrid in my view that is bound to an ObservableCollection in my viewmodel, the issue that I am having is that after I programmtically add an a new Item to my ObservableCollection it appears in the Datagrid however I "Can and Cannot" select it, I know its a sounds a bit wacky but bear with me.
In code its somthing along the lines of:
<DataGrid Grid.Column="0" AutoGenerateColumns="False" ItemsSource="{Binding Path=MyList} SelectedValue{Binding Path=SelectedMyItem}... >
</Datagrid>
Then in my viewmodel:
private ObservableCollection<MyType> myList;
public ObservableCollection<MyType> MyList { get { return myList;} }
privte void AddItem(MyType item)
{
myList.Add(item)
}
public MyType SelectedMyItem {get;set;}
Now what happens is the Datarid gets updated and the new items appears in the grid. However when I try to select it, the grid highlights the previous item in the list, but the black border (that a selected item gets) appears around the new item. Aswell my SelectedValue Binding gets set to the new item. I have also created a context menu that allows user to delete items and when I right click and try to delete the newly added item, it instead deletes the previous item in list.
However when this happens I am then able to properly select the new item. So I am guessing I need away to to refresh the datagrid I am assuming(note if I trigger INotifyPropertyChanged for MyList the sane thing still happens)
EDIT:
public override bool Equals(object obj)
{
var o = obj as MyType;
if (o == null)
return false;
return o.MyTypeId == this.MyTypeId;
}

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

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
}

Categories