I'm using Wpf MVVM, if i know the index number of item/row then how can i search the value in listview/itemsource by specific index number.
Note: i can get index number, index number will already be known.
below is the xaml code for listview
<ListView
Grid.Row="1"
ItemContainerStyle="{StaticResource FileItemStyle}"
ItemsSource="{Binding BarCode, IsAsync=True}"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectedIndex="{Binding SelectedIndex}"
SelectedItem="{Binding SelectBarCode,
UpdateSourceTrigger=PropertyChanged}"
SelectionMode="Single"
Style="{StaticResource ListItemsMain}"
and ObservableCollection for itemsource
private ObservableCollection<BarCodeModel> mBarCode = null;
public ObservableCollection<BarCodeModel> BarCode
{
get
{
mBarCode = mBarCode ?? new ObservableCollection<BarCodeModel>();
return mBarCode;
}
}
and below code is for model
public class BarCodeModel
{
public int BarCodeEntry_ID { get; set; }
public string BarCodeEntry_Title { get; set; }
and below is the command where i want to put my logic
private ICommand mSearchValueByIndexNumberCommand;
public ICommand SearchValueByIndexNumberCommand
{
get
{
if (mSearchValueByIndexNumberCommand == null)
{
mSearchValueByIndexNumberCommand = new DelegateCommand(delegate ()
{
// search BarCodeEntry_ID in BarCode where SelectedIndex is 5 (or other value)
});
}
return mSearchValueByIndexNumberCommand;
}
}
As in your XAML you bind your ListView.ItemsSource to BarCode of your ViewModel, but also bind ListView.SelectedItem and ListView.SelectedIndex to SelectBarCode and SelectedIndex, now, when you select some Item in a ListView, it (ListView) will update values of SelectBarCode and SelectedIndex in your ViewModel.
So, you can access your current selection with SelectBarCode or BarCode[SelectedIndex].
Below is answer to my question, a special thanks to #vasily.sib
private ICommand mSearchValueByIndexNumberCommand;
public ICommand SearchValueByIndexNumberCommand
{
get
{
if (mSearchValueByIndexNumberCommand == null)
{
mSearchValueByIndexNumberCommand = new DelegateCommand(delegate ()
{
int BarCodeId = BarCode[SelectedIndex].BarCodeEntry_ID;
});
}
return mSearchValueByIndexNumberCommand;
}
}
Related
I'm using CollectionViewSource as ItemSource in DataGrid
<DataGrid
ItemsSource="{Binding CollViewSource.View}"
SelectedIndex="{Binding IndexNumber}"
...
and the CollectionViewSource is bound to ObservableCollection in ViewModel
private ObservableCollection<LevelModel> mLevelSource;
public ObservableCollection<LevelModel> LevelSource
{
get
{
mLevelSource = mLevelSource ?? new ObservableCollection<LevelModel>();
return mLevelSource;
}
}
public CollectionViewSource CollViewSource { get; set; }
Model
public class LevelModel : BaseViewModel
{
public string Level_Title { get; set; }
...
In Constructor
CollViewSource = new CollectionViewSource();
CollViewSource.Source = LevelSource;
I have Button inside DataGrid
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button
Command="{Binding DataContext.ViewCommand, RelativeSource={RelativeSource AncestorType=DataGrid}}"
CommandParameter="{Binding}"
Content="View" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
What I want, when i click the Button .i.e ViewCommand it should fetch Level_Title or some other item by Index Number
private ICommand mViewCommand;
public ICommand ViewCommand
{
get
{
if (mViewCommand == null)
{
mViewCommand = new DelegateCommand(delegate ()
{
int indexNumber = IndexNumber;
//string title = // logic should go here
});
}
return mViewCommand;
}
}
For example when index number is 3 then it should fetch the item that exist on 3rd index
Note: I don't want to involve SeletedItem
Try the following on your CollectionView:
LevelModel lm = CollViewSource.View.Cast<LevelModel>().ToArray()[indexNumber];
string title = lm.Level_Title;
I have a multi-column List bound to a ComboBox.
It displays List Column Name as the ItemSource.
Problem
SelectedItem does return the Name.
With MessageBox.Show(vm.cboVideoQuality_SelectedItem); the string shows as MyProgram.ViewModel+VideoQuality instead of High.
I tried filtering Name with:
vm.cboVideoQuality_SelectedItem.FirstOrDefault(s => s.Name);
But it gives error 'char' does not contain definition for Name.
XAML
Bind Item Source and Selected Item.
<ComboBox x:Name="cboVideoQuality"
ItemsSource="{Binding cboVideoQuality_Items, Mode=TwoWay}"
DisplayMemberPath="Name"
SelectedItem="{Binding cboVideoQuality_SelectedItem, Mode=TwoWay}"
SelectedValuePath="Name"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Margin="0,0,0,0"
Width="100" />
ViewModel
// Item Source
//
public class VideoQuality
{
public string Name { get; set; }
public string Bitrate { get; set; }
}
public List<VideoQuality> _cboVideoQuality_Items = new List<VideoQuality>()
{
new ViewModel.VideoQuality() { Name = "High", Bitrate = "5000K" },
new ViewModel.VideoQuality() { Name = "Medium", Bitrate = "2500K" },
new ViewModel.VideoQuality() { Name = "Low", Bitrate = "500K" },
};
public List<VideoQuality> cboVideoQuality_Items
{
get { return _cboVideoQuality_Items; }
set
{
_cboVideoQuality_Items = value;
OnPropertyChanged("cboVideoQuality_Items");
}
}
// Selected Item
//
public string _cboVideoQuality_SelectedItem { get; set; }
public string cboVideoQuality_SelectedItem
{
get { return _cboVideoQuality_SelectedItem; }
set
{
if (_cboVideoQuality_SelectedItem == value)
{
return;
}
_cboVideoQuality_SelectedItem = value;
OnPropertyChanged("cboVideoQuality_SelectedItem");
}
}
C#
I cannot check if selected = "High" because SelectedItem does not equal Name.
It equals MyProgram.ViewModel+VideoQuality.
ViewModel vm = mainwindow.DataContext as ViewModel;
string selected = vm.cboVideoQuality_SelectedItem;
if (selected == "High")
{
// ...
}
You have already used SelectedValuePath and should of course also use SelectedValue instead of SelectedItem:
<ComboBox
ItemsSource="{Binding cboVideoQuality_Items}"
DisplayMemberPath="Name"
SelectedValuePath="Name"
SelectedValue="{Binding cboVideoQuality_SelectedItem}" .../>
As a note, in both Bindings Mode=TwoWay is redundant. An ItemsSource binding is never two-way, while a SelectedValue binding is two-way by default.
I'd also recommend not to use binding target property details in view model property names. E.g. cboVideoQuality_SelectedItem should just be SelectedVideoQuality. Thus you may also bind it to the SelectedValue property of a ListBox or even the Text property of a TextBlock without too much confusion.
I have two windows (views) and they share the same viewmodel. I use one window to input data and the second to order it in 3 different listboxes (observablecollections) based on the value of one combobox in the input window. The problem I have is that the input doesn't show up in the listboxes. it's like the observable collection doesn't update.
This is the code I have in the input window
public partial class AddPerson : Window
{
public NetworkViewModel MyViewModel;
public AddPerson()
{
InitializeComponent();
this.DataContext = new NetworkViewModel();
}
}
and in xaml
<TextBox x:Name="tb_firstName" Text="{Binding Path=FirstName, Mode=TwoWay}"/>
<ComboBox x:Name="cb_group" ItemsSource="{Binding GroupLevel}" SelectedItem="{Binding SelectedGroupLevel}"/>
in the displaywindow with the 3 listboxes I have
public partial class Display : Window
{
public NetworkViewModel MyViewModel;
public AddPerson()
{
InitializeComponent();
this.DataContext = new NetworkViewModel();
}
}
and this is the xaml for the display window
<ListBox x:Name="lb1" GotFocus="textBox1_visible" ItemsSource="{Binding NetworkList1}" dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True" SelectedItem ="{Binding Path=SelectedItemGroup, Mode=TwoWay}" />
<ListBox x:Name="lb2" GotFocus="textBox1_visible" ItemsSource="{Binding NetworkList2}" dd:DragDrop.IsDragSource="True"
dd:DragDrop.IsDropTarget="True" SelectedItem ="{Binding Path=SelectedItemGroup, Mode=TwoWay}" />
This is what my viewmodel looks like
public class NetworkViewModel: INotifyPropertyChanged
{
private ObservableCollection<Person> _networkList1 = new ObservableCollection<Person>();
public ObservableCollection<Person> NetworkList1 //Binds with the listbox
{
get { return _networkList1; }
set { _networkList1 = value; }
}
private string _firstName;
public string FirstName
{
get { return this._firstName; }
set { this._firstName = value; NotifyPropertyChanged("FirstName"); }
}
private string _group;
public string Group
{
get { return _group; }
set { _group = value; NotifyPropertyChanged("Group"); }
}
public NetworkViewModel()
{
AddPersonCommand = new RelayCommand(AddPerson);
}
private ICommand _addPersonCommand;
public ICommand AddPersonCommand
{
get { return _addPersonCommand; }
set { _addPersonCommand = value; }
}
public void AddPerson(object obj)
{
if (SelectedGroupLevel == "Primary")
{
NetworkList1.Add(new Person()
{
FirstName = this.FirstName,
Group = this.Group,
});
MessageBox.Show("Person successfully added");
}
else if (SelectedGroupLevel == "Secondary")
{
NetworkList2.Add(new Person()
{
FirstName = this.FirstName,
Group = this.Group,
});
MessageBox.Show("Person successfully added");
}
}
When I click the add button in the input window I can see the message in the messagebox, which means that the data is added to the observable collection, but I don't see it displayed, Hopefully somebody can help me with this issue. I'm very green to wpf and mvvm. Thanks.
Problem lies in the way you are using view models. You are creating two separate instances of your view model one in the AddPerson view and one in the Display view. When you add an item in the AddPerson view it is updating its own view model not the Display view's view model.
You need a way two communicate the changes from one view model to the other.
Please look at the image below:
Only three items in the listbox are displayed in the above image but it can be any number of items depending on the user's choice.
Now, as you can see in the image above each item has two comboboxes. Now I want to have selectedItem or SelectedValue in my viewModel from which I should be able to get the user's selection. Now I don't know how to bind these comboboxes for getting the user's selection.
Suppose I have only one item instead of the list then I would declare a property of type int so that I can easily get the selectedValue but for the list I am very much confused. Can anybody point me to the right direction?
To start of, lets say the class you are going to be binding the combo box is
public class UnitSource :INotifyPropertyChanged
{
public IEnumerable Units
{
get { return new[] { "Test Unit", "Alternate Unit" }; }
}
string _selectedComboItem1;
public string SelectedComboItem1
{
get
{
return _selectedComboItem1;
}
set
{
if (_selectedComboItem1 == value)
return;
_selectedComboItem1 = value;
OnPropertyChanged();
}
}
string _selectedComboItem2;
public string SelectedComboItem2
{
get
{
return _selectedComboItem2;
}
set
{
if (_selectedComboItem2 == value)
return;
_selectedComboItem2 = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Then in your view model you will have an ObservableCollection of the UnitSource Like below
public ObservableCollection<UnitSource> MuchoUnitSources
{
get; set;
}
To get the selected ListBoxItem have this in your ViewModel
private UnitSource _selectedUnitSource;
public UnitSource SelectedUnitSource
{
get
{
return _selectedUnitSource;
}
set
{
if (_selectedUnitSource == value)
return;
_selectedUnitSource = value;
OnPropertyChanged();
}
}
Lets assume it is initialized like so
MuchoUnitSources = new ObservableCollection<UnitSource>(new []{ new UnitSource(),new UnitSource() });
The in your view your listbox should look like below
<ListBox Name ="TestList1" ItemsSource="{Binding MuchoUnitSources}" SelectedItem="{Binding SelectedUnitSource}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<ComboBox SelectedItem="{Binding SelectedComboItem1}" ItemsSource="{Binding Units}" />
<ComboBox SelectedItem="{Binding SelectedComboItem2}" ItemsSource="{Binding Units}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Now whenever you select an item from any of the combobox they will update the objectbeing bound to.
I am not able to find out Why is combo box binding not working?
I have a view model which looks like (2 properties)
public ProcessMaintenanceDataObject CurrentProcess
{
get
{
return _CurrentProcess;
}
set
{
_CurrentProcess = value;
OnPropertyChanged("CurrentProcess");
}
}
public ObservableCollection<ProcessMaintenanceDataObject > Processes
{
get
{
return _Processes;
}
set
{
_Processes = value;
OnPropertyChanged("Processes");
}
}
public ObservableCollection<FolderInfo> Folders
{
get
{
return _folders;
}
set
{
_folders = value;
OnPropertyChanged("Folders");
}
}
The following is the ProcessMaintenanceDataObject definition
[DataMember]
public string ProcessName
{
get
{
return _ProcessName;
}
set
{
_ProcessName = value;
OnPropertyChanged("ProcessName");
}
}
[DataMember]
public string Id
{
get
{
return _Id;
}
set
{
_Id = value;
OnPropertyChanged("Id");
}
}
[DataMember]
public string FolderId
{
get
{
return _FolderId;
}
set
{
_FolderId = value;
OnPropertyChanged("FolderId");
}
}
[DataMember]
public FolderInfo Folder
{
get
{
return _Folder;
}
set
{
_Folder = value;
if (_Folder != null)
FolderId = _Folder.FolderId;
OnPropertyChanged("Folder");
}
}
The FolderInfo class has FolderName and FolderId Property.
I have a method in viewmodel which fills the Processes.
In my view I have structure something like, I have a treeview which will be bound to Processes and while selecting any of the item from the treeview, i need to allow user to edit that entity.
In the view the combo box binding is as:
<ComboBox ItemsSource="{Binding Path=Folders, Mode=OneWay}"
DisplayMemberPath="FolderName"
SelectedItem="{Binding Source={StaticResource viewModel}, Path=CurrentProcess.Folder, Mode=TwoWay}">
...
This binding doesn't work I mean when I select any object from the tree it fills other information like ProcesName in the textBox but it doesn't make the Folder object as the selected item in combobox, however the combo box will be filled.
Any suggestion.
Do refer this:
If you want to bind a ComboBox to your folders property in two way mode with edit support,
Then you should define data template for your combo box and then bind properties of FolderInfo class to those text boxes
Binding display member path will not solve your problem
I'd suggest you to change DisplayMemberPath with appropriate DataTemplate:
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding FolderName}">
</StackPanel>
<DataTemplate>
This will fix SelectedItem context.
Maybe just maybe, your Folderinfo class is not a notificationObject. If it is the case make sure it implements INotifyPropertyChange.
you have to use SelectedValuePath and SelectedValue instead of SelectedItem like below,
<ComboBox ItemsSource="{Binding Path=Folders, Mode=OneWay}"
DisplayMemberPath="FolderName"
SelectedValuePath="FolderId"
SelectedValue="{Binding Path=FolderId, Mode=TwoWay}">
SelectedItem binds the whole object whereas SelectedValue binds only particular properties of the object.