Data Binding issues in "MultiSelect Comboboxes inside a ListView" - wpf

Please help me out,
i have to populate multiselect comboboxes insode listview.
i implemented multiselect combobox and i integrated it to Listview. but i am unable to manage databinding part.
this is my XAML Code
<Window.Resources>
<Task:Task x:Key="Task"/>
</Window.Resources>
<Grid Width="278">
<ListView Name="XAxisAttributesList" Padding="2"
SelectionMode="Single"
Visibility="Visible" Margin="0,0,22,0"
DataContext="{Binding Source={StaticResource Task}}"
ItemsSource="{Binding Path=AllItems}">
<ListView.View>
<GridView>
<GridViewColumn Header="X Axis" Width="{Binding ElementName=XAxisAttributesList, Path=ActualWidth}">
<GridViewColumn.CellTemplate>
<DataTemplate>
<control:MultiSelectComboBox x:Name="MC" Width="150" Height="30"
DataContext="{Binding Source={StaticResource Task}, Path=AllItems/ModelObject}"
ItemsSource="{Binding Items}"
SelectedItems="{Binding SelectedItems}"
Text="{Binding DisplayTitle}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
Task.cs
public class Task
{
string Name;
static ViewModel modelObject;
static ObservableCollection<Task> allItems;
public Task()
{
Task.CreateTasks();
}
public ObservableCollection<Task> AllItems
{
get { return allItems; }
set { allItems = value; }
}
public Task(string Name, ViewModel _modelObject)
{
this.Name = Name;
modelObject = _modelObject;
}
public static void CreateTasks()
{
ObservableCollection<Task> list = new ObservableCollection<Task>();
List<string> all = new List<string>();
all.Add("1");
all.Add("2");
all.Add("3");
List<string> selected=new List<string>();
selected.Add("1");
list.Add(new Task("Item1", new ViewModel(new MultiSelectDemo.Attribute(all, selected, "Item1"))));
list.Add(new Task("Item2", new ViewModel(new MultiSelectDemo.Attribute(all, selected, "Item2"))));
list.Add(new Task("Item3", new ViewModel(new MultiSelectDemo.Attribute(all, selected, "Item3"))));
allItems = list;
}
public string Option
{
get { return this.Name; }
}
public ViewModel ModelObject
{
get { return modelObject; }
}
}
please
see the image here
instead of populating item 1,item 2 and item 3 it populating only item3 all the time

There is actually two problems:
The first problem is:
DataContext="{Binding Source={StaticResource Task}, Path=AllItems/ModelObject}"
should be DataContext="{Bindind ModelObject}"
The second problem is that static ViewModel modelObject; should not be static.

Related

Unselect WPF DataGrid when ItemsSource changed

I have the following DataGrid in WPF :
<DataGrid x:Name="dgPatientMedicationOrderList" Width="Auto" HorizontalAlignment="Stretch" RowHeight="40" Background="Transparent" HorizontalContentAlignment="Left"
GridLinesVisibility="None" RowHeaderWidth="0" VirtualizingStackPanel.VirtualizationMode="Standard" SelectedIndex="-1"
ScrollViewer.HorizontalScrollBarVisibility="Disabled" AutoGenerateColumns="False" SelectionMode="Single"
IsSynchronizedWithCurrentItem="True" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Stretch" IsReadOnly="True"
ItemsSource="{Binding PatientOrdersCollectionView}">
When a user clicks on a row in the DataGrid, it's SelectionChanged event is fired and the bound ViewModel command drives the View to load another user control corresponding to the DG row. In my view I am changing my datagrid's source binding from my ViewModel. Now the problem is that every time the ItemsSource is changed the SelectionChanged event is fired selecting the first item in the DataGrid; this is followed by the view loading the user control without the user explicitly selecting the DataGrid row. How can I prevent the DataGrid from selecting any Row when it's ItemsSource is changed ?
Simplified Demo Code:
XAML:
<Button Content="Change Source" Command="{Binding ChangeItemsSourceCmd}" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,20" />
<StackPanel VerticalAlignment="Bottom" HorizontalAlignment="Left" Orientation="Vertical">
<TextBlock Text="{Binding SelectedPerson.Id, StringFormat=ID: {0}}" />
<TextBlock Text="{Binding SelectedPerson.Name, StringFormat=Name: {0}}" />
<TextBlock Text="{Binding SelectedPerson.Gender, StringFormat=Gender: {0}}" />
<TextBlock Text="{Binding SelectedPerson.Country, StringFormat=Country: {0}}" />
</StackPanel>
</Grid>
ViewModel:
public class WindowViewModel : ViewModelBase
{
private Person _selectedPerson;
private ObservableCollection<Person> _personList;
public Person SelectedPerson
{
get { return _selectedPerson; }
set { RaisePropertyChange<Person>(() => SelectedPerson, ref _selectedPerson, ref value); }
}
public ObservableCollection<Person> PersonList
{
get { return _personList; }
set
{
SelectedPerson = null;
RaisePropertyChange<ObservableCollection<Person>>(() => PersonList, ref _personList, ref value);
}
}
public WindowViewModel()
{
PersonList = new ObservableCollection<Person>()
{
new Person() { Id=101, Name="Mahesh", Gender="Male", Country="India"},
new Person() { Id=102, Name="Srinivas", Gender="Male", Country="Sri Lanka"},
new Person() { Id=103, Name="Isha", Gender="Female", Country="United States"},
new Person() { Id=104, Name="Salim", Gender="Male", Country="Pakistan"}
};
}
public ICommand ChangeItemsSourceCmd
{
get
{
return new RelayCommand(ChangeItemsSourceCmdHandler);
}
}
private void ChangeItemsSourceCmdHandler()
{
PersonList = new ObservableCollection<Person>()
{
new Person() { Id=105, Name="Raman", Gender="Male", Country="Uganda"},
new Person() { Id=106, Name="Anurag", Gender="Male", Country="England"},
new Person() { Id=107, Name="Komal", Gender="Female", Country="Thailand"},
new Person() { Id=108, Name="Nitin", Gender="Male", Country="Africa"}
};
}
}
You should:
1.Add a SelectedItem Binding in your DataGrid:
SelectedItem="{Binding Selected, Mode=TwoWay}"
2.Have the related property (firing PropertyChanged of course)
public object Selected
{
get { return selected; }
set
{
selected = value;
OnPropertyChanged("Selected");
}
}
3.Set it to null in your Itemssource setter (or before you change it)
public IEnumerable PatientOrdersCollectionView
{
get { return patientOrdersCollectionView; }
set
{
Selected = null; // Put it to null here to unselect it from grid
patientOrdersCollectionView = value;
OnPropertyChanged("PatientOrdersCollectionView");
}
}
Should do the trick.

An ObservableCollection of StackPanel as ItemsSource of ComboBox in WPF

I am having problem binding ObservableCollection as ItemsSource to a combo box (this combobox is in a listview of having some rows).
I followed A collection of StackPanel as ItemsSource of ComboBox but I did not get any clues for resolving my problem.
Problem:
I was able to add items to a combobox which is at the top on the form.
I have created a listview containing 3 text blocks and 1 combobox.
I am successful in populating data for the text blocks in listview.
But the problem lies with Combobox. First time, it shows all the items for each row in ListView. Once I select item or click on the combobox again to see the items, my list disappears. Only one combobox in the listview row shows all items. Other comboboxes shows blank.
Also, I was trying to save the index of the selected item and show the selected panel next time. But I did not get how to bind the stackpanel with selecteditem and selecteditemvalue.
I tried many ways of directly binding the items to the combobox in listview. But nothing worked. Request someone to help me on this.
Details of the code is given below:
I have XAML like below:
<Grid>
<Grid Height="40">
<ComboBox x:Name="cbList" />
</Grid>
<Grid Margin="0,56,0,168"></Grid>
<ListView x:Name="lvFirst" Margin="0,195,0,12">
<ListView.View>
<GridView >
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Width="50" x:Uid="tbListView1" Text="{Binding FirstName}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Width="50" x:Uid="tbListView2" Text="{Binding LastName}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Width="50" x:Uid="tbListView1" Text="{Binding ID}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn>
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox Width="100" x:Uid="cbListView" ItemsSource="{Binding Path=SPForComboBox}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
In the code behind I have a Contact class as below:
public class Contact : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
void Notify(string propName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propName));
}
}
private string _fn;
private string _ln;
public string FirstName
{
get
{ return _fn; }
set
{ _fn = value; Notify("FirstName"); }
}
public string LastName
{
get
{ return _ln; }
set
{ _ln = value; Notify("LastName"); }
}
private int _id;
public int ID
{
get { return _id; }
set { _id = value; Notify("ID"); }
}
public StackPanel sp;
public override string ToString()
{
return FirstName + " " + LastName;
}
private ObservableCollection<StackPanel> _sp;
public ObservableCollection<StackPanel> SPForComboBox
{
get { return _sp; }
set { _sp = value; Notify("SPForComboBox"); }
}
}
To populate cbList Items, I am repeatedly calling below function after Initialization() function:
private void AddColours(string name, byte hexcolor)
{
//Add this ShiftType to Combo box
SolidColorBrush rectangleBrush = new SolidColorBrush();
Color color = new Color();
color.A = hexcolor;
rectangleBrush.Color = color;
System.Windows.Controls.StackPanel stkPanel = new StackPanel(); //stack panel to hold rectangle + text
stkPanel.Orientation = Orientation.Horizontal;
cbList.Items.Add(stkPanel);
Rectangle colorRect = new Rectangle(); //rectangle showing colour for shift
colorRect.Height = 12;
colorRect.Width = colorRect.Height;
colorRect.Fill = rectangleBrush;
stkPanel.Children.Add(colorRect);
System.Windows.Controls.TextBlock cboText = new TextBlock(); //Name of shift
cboText.Text = name;
cboText.Margin = new Thickness(5, 5, 5, 5);
stkPanel.Children.Add(cboText);
}
In the main window class, I have a created an ObservableCollection object as public static (object name is contacts).
public static ObservableCollection<Contact> contacts = new ObservableCollection<Contact>();
After the Initialization() function, I am populating contacts as below:
AddColours("First", 100);
AddColours("Second", 50);
AddColours("Third", 20);
AddColours("Fourth", 0);
AddColours("Fifth", 80);
Contact c1 = new Contact();
c1.FirstName = "Digo";
c1.LastName = "Maradona";
c1.ID = 0;
c1.SPForComboBox = new ObservableCollection<StackPanel>();
foreach (StackPanel sp in cbList.Items)
{
c1.SPForComboBox.Add(sp);
}
Contact c2 = new Contact();
c2.FirstName = "Brian";
c2.LastName = "Lara";
c2.ID = 1;
c2.SPForComboBox = new ObservableCollection<StackPanel>();
foreach (StackPanel sp in cbList.Items)
{
c2.SPForComboBox.Add(sp);
}
Contact c3 = new Contact();
c3.FirstName = "Sachin";
c3.LastName = "Tendulkar";
c3.ID = 2;
c3.SPForComboBox = new ObservableCollection<StackPanel>();
foreach (StackPanel sp in cbList.Items)
{
c3.SPForComboBox.Add(sp);
}
contacts.Add(c1);
contacts.Add(c2);
contacts.Add(c3);
lvFirst.ItemsSource = contacts;
HighCore, Thank you very much for the links. I have existing implementation and adding combobox to that.
I too felt that the method followed is not good. I shall certainly look at the alternatives provided by you and suggested by pushpraj.
Answer:
I thought referring objects in other combobox will work till the items exist in that combobox. But I need to create rectangle and textblock for reach combobox I am creating and for each entry in that combobox.
So certainly I need to do it in foreach loop.
Also, once I do this I can use SelectedIndex referring to the integer and SelectedItem to sp (individual stackpanel in that class).
This method is not good to follow but might be helpful for somebody.
Thanks.

wpf databinding combobox within treeview

I am very new to WPF, and help appreciated:
Model:
Collection<Presenter>,
Presenter has a Collection<Presentation>,
Presentation has a TeachingSession property (which contains a DateTime? property)
I am trying to have a treeview display:
presenter name
[combobox of available Dates]
At the moment, each presenter name in the treeview is displaying correctly, and the first parent item expanded displays the combobox with the correctly selected date. However, comboboxes displaying at any one time are all 'in sync' - that is changing the value in a combobox (or expanding a different treeview item) changes the value for all comboboxes which can be seen, so they all display the same date.
<TreeView Name="PresenterTreeView" ItemsSource="{Binding}">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Presenter}"
ItemsSource="{Binding Path=Presentations}">
<TextBlock Text="{Binding Path=FullName}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Presentation}">
<ComboBox SelectedItem="{Binding Path=TeachingSession, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="SessionDate"
ItemsSource="{Binding Source={StaticResource availableDatesViewSource}}" >
</ComboBox>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
I have compliled your example and I cant get the comboboxes to sync like you are describing.
Perhaps you will be able to see what I done different and it might be the fix, Or maybe I am just wrong and am missing somthing from your question?
This is the code I used:
Xaml:
<Window x:Class="WpfApplication8.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="340" Width="480" Name="UI" xmlns:local="clr-namespace:WpfApplication8">
<TreeView Name="PresenterTreeView" DataContext="{Binding ElementName=UI}" ItemsSource="{Binding Path=Presenters}" >
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Presenter}" ItemsSource="{Binding Path=Presentations}">
<TextBlock Text="{Binding FullName}" />
</HierarchicalDataTemplate>
<HierarchicalDataTemplate DataType="{x:Type local:Presentation}">
<ComboBox SelectedItem="{Binding TeachingSession.SessionDate}" ItemsSource="{Binding ElementName=UI, Path=Dates}" />
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
</Window>
Code:
public partial class MainWindow : Window
{
private ObservableCollection<Presenter> _myProperty = new ObservableCollection<Presenter>();
private ObservableCollection<DateTime?> _myDates = new ObservableCollection<DateTime?>();
public MainWindow()
{
InitializeComponent();
DateTime time1 = DateTime.Now;
DateTime time2 = DateTime.Now.AddDays(1);
Dates.Add(time1);
Dates.Add(time2);
for (int i = 0; i < 20; i++)
{
Dates.Add(DateTime.Now.AddDays(i));
}
TeachingSession teach = new TeachingSession { SessionDate = time1 };
Presentation pres = new Presentation { TeachingSession = teach };
Presenter presenter = new Presenter { FullName = "Presenter1" };
presenter.Presentations = new ObservableCollection<Presentation>();
presenter.Presentations.Add(pres);
TeachingSession teach1 = new TeachingSession { SessionDate = time2 };
Presentation pres1 = new Presentation { TeachingSession = teach1 };
Presenter presenter1 = new Presenter { FullName = "Presenter1" };
presenter1.Presentations = new ObservableCollection<Presentation>();
presenter1.Presentations.Add(pres1);
Presenters.Add(presenter);
Presenters.Add(presenter1);
}
public ObservableCollection<Presenter> Presenters
{
get { return _myProperty; }
set { _myProperty = value; }
}
public ObservableCollection<DateTime?> Dates
{
get { return _myDates; }
set { _myDates = value; }
}
}
public class Presenter
{
public string FullName { get; set; }
public ObservableCollection<Presentation> Presentations { get; set; }
}
public class Presentation
{
public TeachingSession TeachingSession { get; set; }
}
public class TeachingSession
{
public DateTime? SessionDate { get; set; }
}
Result:
Because of sa_ddam213's answer, i was able to track the problem down to the default synchronisation with the CollectionViewSource used to bindItemsSource
The combobox needed the attribute:
IsSynchronizedWithCurrentItem="False"

Failing to add items in listbox on button Click

I am a newbie to MVVM. I have two grid's inside by main window where one grid contains a listbox towards left side and other grid on the right side contains list view and 2 buttons.
I am able to add items to listview and even figure out how to get the selected item from list view. Once I select the item on list view and click a button(Connect), listbox towards left shud get updated with items which I have added from viewmodel class.
View below shows Listbox towards my left:
<Grid Grid.Column="0" Name="BoardTabSelect" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<ListBox Name="ButtonPanel"
ItemsSource="{Binding BoardTabs, Mode=TwoWay}"
SelectedItem="{Binding SelectedTab, Mode=TwoWay}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Name="BoardtabChanger"
Margin="53,27,0,0"
Text="{Binding TabOperation}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
View below shows listview towards Right along with 2 Buttons:
<Grid Grid.Row="0" Name="MainConnectGrid" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<ListView Name="listView"
ItemsSource="{Binding Products}"
SelectedItem="{Binding SelectedProduct, Mode=TwoWay}">
<ListView.View>
<GridView>
<GridViewColumn Width="300"
Header="Name"
DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Width="283"
Header="Connection Status"
DisplayMemberBinding="{Binding Connection_Status}" />
</GridView>
</ListView.View>
</ListView>
<Button Content="Connect"
Height="23" Width="100"
HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="55,519,0,0"
Name="ConnectBtnGrid"
Command="{Binding Path=ConnectCommand}" />
<Button Content="Disconnect"
Height="23" Width="100"
HorizontalAlignment="Left" VerticalAlignment="Top"
Margin="446,519,0,0"
Name="DisconnectBtn"
Command="{Binding Path=DisconnectCommand}" />
</Grid>
VIEW MODEL:
public class ProductViewModel : INotifyPropertyChanged
{
public List<Product> m_Products;
public List<Product> m_BoardTabs;
public ProductViewModel()
{
m_Products = new List<Product>()
{
new Product() {Name = "Bavaria", Connection_Status = "Disconnected"},
new Product() {Name = "Redhook", Connection_Status = "Disconnected"},
};
m_BoardTabs = new List<Product>()
{
new Product() {TabOperation = "Connect"}
};
}
public List<Product> Products { get; set; }
public List<Product> BoardTabs { get; set; }
private Product m_SelectedItem;
public Product SelectedProduct
{
get { return m_SelectedItem; }
set
{
m_SelectedItem = value;
NotifyPropertyChanged("SelectedProduct");
}
}
private Product m_SelectedTab;
public Product SelectedTab
{
get { return m_SelectedTab; }
set
{
m_SelectedTab = value;
NotifyPropertyChanged("SelectedTab");
}
}
private ICommand mUpdater;
public ICommand ConnectCommand
{
get
{
if (mUpdater == null)
mUpdater = new DelegateCommand(new Action(SaveExecuted), new Func<bool>(SaveCanExecute));
return mUpdater;
}
set { mUpdater = value; }
}
public bool SaveCanExecute()
{
return true;
}
public void SaveExecuted()
{
if (SelectedProduct.Connection_Status == "Disconnected" && SelectedProduct.Name == "Bavaria")
{
SelectedProduct.Connection_Status = "Connected";
m_BoardTabs.Add(new Product() { TabOperation = "I2C" });
m_BoardTabs.Add(new Product() { TabOperation = "Voltage" });
m_BoardTabs.Add(new Product() { TabOperation = "Codec" });
}
}
}
Inside the Save Executed method I am trying to add the items in listbox but when I run the application and select item from listview and press CONNECT Btn, the list does not get updated. My model class is complete with all three properties (Name, Connection Status and TabOperation)
BoardTabs and Products need to be an ObservableCollection<Product>. Otherwise WPF doesn't get informed about new items in the lists and thus can't update the UI.
Check properies of ProductViewModel. It implements INotifyPropertyChanged , and in Products, BoardTabs, you not notify the change .
public List<Product> Products
{
get
{
return m_Products;
}
set
{
m_Products = value;
NotifyPropertyChanged("Products")
}
}
public List<Product> BoardTabs
{
get
{
return m_BoardTabs;
}
set
{
m_BoardTabs = value;
NotifyPropertyChanged("BoardTabs")
}
}

Why the databinding fails in ListView (WPF)?

I have a ListView of which ItemSource is set to my Custom Collection.
I have defined a GridView CellTemplate that contains a combo box as below :
<ListView
MaxWidth="850"
Grid.Row="1"
SelectedItem="{Binding Path = SelectedCondition}"
ItemsSource="{Binding Path = Conditions}"
FontWeight="Normal"
FontSize="11"
Name="listview">
<ListView.View>
<GridView>
<GridViewColumn
Width="175"
Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox
Style="{x:Null}"
x:Name="TypeCmbox"
Height="Auto"
Width="150"
SelectedValuePath="Key"
DisplayMemberPath="Value"
SelectedItem="{Binding Path = MyType}"
ItemsSource="{Binding Path = MyTypes}"
HorizontalAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</ListView>
public MyType : INotifyPropertyChanged
{
string Key;
string Value;
public string Key { get { return _key; }
set { _key = value; this.OnPropertyChanged("Key"); } }
public string Value { get { return _value; }
set { _value = value; this.OnPropertyChanged("Value"); } }
public MyType ()
{
}
public MyType (string key, string value)
{
_key = key;
_value = value;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
#endregion
}
public void MoveUpExecuted()
{
int oldIndex = this.Conditions.IndexOf(_selectedCondition);
//Check if the selected item is not the first item
if (oldIndex != 0)
{
int newIndex = oldIndex - 1;
this.Conditions.Move(oldIndex, newIndex);
}
}
My Custom collection is the ObservableCollection.
I have a two buttons - Move Up and Move Down on top of the listview control . When user clicks on the Move Up or Move Down button I call Move method of Observable Collection.
But when I Move Up and Move Down the rows then the Selected Index of a combo box is -1.
I have ensured that selectedItem is not equal to null when performing Move Up and Move Down commands.
Please Help!!
I don't get this part:
I call MoveUp and MoveDown methods of
Observable Collection.
ObservableCollection does not have such methods, at least not to my knowledge? Neither has it a notion of a current item or similar.
My apologies if I have missed something that could possibly render this post as ignorant.
What you could do is instead of binding your ListView to an ObservableCollection, you could bind it to a ICollectionView (derived from your ObservableCollection). If you set IsSynchronizedWithCurrentItem=True on ListView, you won't need to bind SelectedItem, it will be automatically bound to CurrentItem on ICollectionView.
ICollectionView also implements MoveCurrentToNext and MoveCurrentCurrentToPrevious which can be bound from your buttons (via ICommand).
EDIT:
Now that new information is on the table, my above answer is not really relevant anymore. But I don't (yet) know the SO convention how to handle this, if I should delete the post entirely, edit out the above or just add the "new" reply. For now I'll edit this post.
I tried to recreate your project and your problem. Hopefully I have understood your problem right, and recreated it similarly at least.
As in the problem being the combobox not holding its value when it is being moved in the listview, it works for me.
Below are the relevant code (some of it hidden to avoid too much noise).
Does this help you?
public class MainWindowViewModel:INotifyPropertyChanged
{
private Condition _selectedCondition;
public ObservableCollection<Condition> Conditions { get; set; }
public Condition SelectedCondition
{
get
{
return _selectedCondition;
}
set
{
if (_selectedCondition != value)
{
_selectedCondition = value;
OnPropertyChanged("SelectedCondition");
}
}
}
...
public void MoveUpExecuted()
{
int oldIndex = this.Conditions.IndexOf(_selectedCondition);
//Check if the selected item is not the first item
if (oldIndex != 0)
{
int newIndex = oldIndex - 1;
this.Conditions.Move(oldIndex, newIndex);
}
}
And the condition class:
public class Condition : INotifyPropertyChanged
{
private MyType myType;
public ObservableCollection<MyType> MyTypes { get; set; }
public MyType MyType
{
get { return myType; }
set
{
if (myType != value)
{
myType = value;
OnPropertyChanged("MyType");
}
}
}
public Condition()
{
MyTypes = new ObservableCollection<MyType>() { new MyType() { Key = "1", Value = "One" }, new MyType() { Key = "2", Value = "Two" } };
MyType = MyTypes[1];
}
... etc
<ListView
SelectedItem="{Binding Path=SelectedCondition}"
ItemsSource="{Binding Path=Conditions}"
FontWeight="Normal"
FontSize="11"
Name="listview" Margin="0,32,0,0">
<ListView.View>
<GridView>
<GridViewColumn
Width="175"
Header="Type">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox
Width="150"
SelectedValuePath="Key"
DisplayMemberPath="Value"
SelectedItem="{Binding Path=MyType}"
ItemsSource="{Binding Path=MyTypes}"
HorizontalAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Button Content="Move up"
Command="{Binding MoveUpCommand}"
/>
Swap these lines:
SelectedItem="{Binding Path = SelectedCondition}"
ItemsSource="{Binding Path = Conditions}"
ItemSource needs to be before the SelectedItem
Did you try ItemsSource="{Binding Conditions}"

Resources