Pass DropDown value to RelayCommand in WPF MVVM - wpf

This is my Code in XAML.
<telerik:RadComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" ></telerik:RadComboBox>
<telerik:RadButton Name="BtnExportToPdf" Content="Export To PDF" Command="{Binding ExportToPDFClickCommand}"></telerik:RadButton>
Below is my RelayCommand in ViewModel
public ICommand ExportToPdfClickCommand
{
get
{
return new RelayCommand(ExportReportData);
}
}
I want to pass Dropdown Value to Relay Command. How can I do this ?

Why do you need to pass the selected item to your command?
Your viewmodel already has that value:
SelectedItem="{Binding SelectedItem}"
As a result, just refrence your SelectedItem property within your view-model.

Related

How to bind itemsource in combobox based on another combox items in wpf?

If i have items in one combobox are CFG_REG,INT_REG,ST_REG,CMD_REG(which are defined in enum), if i select item CFG_REG then i should display GCR,PCR,LCR,CR,GSR,PSR in another combobox similarly,if i select INT_REG i should display IE,IS like that,.. How do i do that?
<ComboBox Grid.Column="2"
Grid.Row="1"
SelectedIndex="{Binding CMDIndex, Mode=TwoWay}"
x:Name="Combobox1"
Margin="0,0,1,0"
VerticalAlignment="Top">
</ComboBox>
<ComboBox Grid.Column="3" IsTextSearchEnabled="True"
Grid.Row="1"
x:Name="combobox2"
ItemsSource="{Binding }"
SelectedItem="{Binding RegisterIndex,Mode=TwoWay}"
VerticalAlignment="Top" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="Name"
Margin="0,0,1,0">
</ComboBox>
You should bind a collection of items (i.e. ICollection or Observable collection) in your view model/Code to the first Combo box's itemsSource. You can bind the 'SelectedItem' of the first combo box to a property in the code behind/view model and then in the setter of this property, you should filter out another Collection which will be bound to other Combo box. I hope you get the idea.
For example:
<ComboBox ItemsSource ={Binding Collection1} SelectedItem ={Binding SelectedItem} .../>
In the Code:
public ICollection Collection1 {get;set;}
public ICollection Collection2 {get;set;}
public string SelectedItem
{
get {..}
set{
SelectedItem = value;
ChangeSecondCollection(value);
}
public void ChangeSecondCollection(string value)
{
Collection2 = //Filter your second collection here.
}

Unable to get the binding from textbox and bind combobox from another view model

I am farily new to mvvm so bear with me. I have 2 View models which are inherited namely DBViewModel and PersonViewModel. i would like to add the person object in DBViewModel and bind 2 combobox with observablecollection in PersonViewModel.
public class PersonViewModel
{
private ICommand AddCommand ;
public Person PersonI{get;set;}
public ObservableCollection<Person> EmployeeList{ get; set; }
public ObservableCollection<String> OccupationList{ get; set; }
public PersonViewModel()
{
PersonI = new Person();
this.AddCommand = new DelegateCommand(this.Add);
// get OccupationList and EmployeeList
}
......
}
public class DBViewModel : PersonViewModel
{
public PersonViewModel PersonVM { get; set; }
public PersonViewModel()
{
PersonVM = new PersonViewModel();
}
....
}
<DataTemplate DataType='{x:Type viewModel:DBViewModel}'>
<StackPanel>
<TextBox Text="{Binding PersonI.Name}" />
<ComboBox Name="cboccupation" ItemsSource="{Binding OccupationList}"
DisplayMemberPath="Name"
SelectedItem="{Binding SelectedItem}" SelectedValuePath="Id"/>
<Button Content="Add" Command="{Binding AddCommand}" />
<DataGrid ItemsSource="{Binding EmployeeList}" CanUserAddRows="True">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Occupation">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding OccupationList}"
DisplayMemberPath="Name" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</StackPanel>
</DataTemplate>
if you want an easier approach I'm thinking you could set a datastore field using blend and bind both controls to that field.
Your bindings are trying to bind to the properties PersonI and OccupationList on the DBViewModel, however those properties do not exist.
You need to point them to the PersonVM.PersonI and PersonVM.OccupationList instead.
<TextBox Text="{Binding PersonVM.PersonI.Name}" />
<ComboBox ItemsSource="{Binding PersonVM.OccupationList}" ... />
For your ComboBox binding inside the DataGrid, that probably will not work because the DataContext of each row in the Grid is a Person object (specified by the DataGrid.ItemsSource), and I don't think Person has a property called OccupationList.
You need to change the Source of your binding to use the object that has the OccupationList property.
For example, if your DataGrid was named MyDataGrid, the following binding for that ComboBox would work
<ComboBox ItemsSource="{Binding
ElementName=MyDataGrid,
Path=DataContext.PersonVM.OccupationList}" ... />
Alternatively, you could use a RelativeSource binding to have it look for the parent DataGrid object without needing to specify a name
<ComboBox ItemsSource="{Binding
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
Path=DataContext.PersonVM.OccupationList}" ... />
As a side note, you seem to be a bit confused about bindings and the DataContext. I like to blog about beginner WPF topics, and would recommend reading What is this "DataContext" you speak of?. I find it has helped many WPF beginners on this site understand the basic binding concept. :)

how to remove custome items from observablecollection in silverlight

i binded one observable cllection to one listbox in silverlight.when i click one item in listbox and click delete button ,how to remove that particular item remove from the listbox without linq using mvvm.i passed commandparameter of the button is listbox itemid.
<ListBox ItemsSource="{Binding School1,Mode=TwoWay}" DisplayMemberPath="SchoolName" Name="listBox1" >
<Button Content="Delete" Command="{Binding deletecommand}" CommandParameter="{Binding Path=SelectedItem.ID,ElementName=listBox1}" Name="button2" />
so what is the code for remove particular item from observable collection
public void delete(object parameter)
{
School1.Remove(...)
}
Bind the ListBox's SelectedItem to a property and use that in your Remove():
<ListBox ItemsSource="{Binding School1, Mode=TwoWay}"
DisplayMemberPath="SchoolName"
SelectedItem={Binding SelectedSchool}
Name="listBox1"
/>
public void delete(object parameter)
{
if (SelectedSchool != null)
School1.Remove(SelectedSchool);
}
Also note that your question is somewhat of a duplicate: Clearing selecteditem of listbox (which is bound to collection of objects) with MVVM

How to fire event from button inside datagrid in silverlight and MVVM

I have button at first column in datagrid. I am using MVVM and try to bind Command to Command in ViewModel but when I click button in each row, it don't work (It don't call Command in ViewModel) but if I move that button out of datagrid it's working properly.
How can I fire event from button inside datagrid in MVVM?
Update 1:
XAML's code is:
<datagrid:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center">
<Button x:Name="button" Content="View" Margin="5" DataContext="{StaticResource XDataContext}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding ViewOrganizationCommand}"
CommandParameter="{Binding ElementName=dtgOrganizations, Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
</DataTemplate>
</datagrid:DataGridTemplateColumn.CellTemplate>
ViewModel's code is:
public ViewModelCommand ViewOrganizationCommand { get; set; }
Instead of using EventTrigger, why not simply bind to Button.Command directly, like so?
<Button
...other properties...
Command="{Binding ViewOrganizationsCommand}"
CommandParameter="{Binding}"/>
That will bind the command, and set the CommandParameter to the DataContext of the Button, which presumably is a good thing to bind the parameter to. If it's not, just bind CommandParameter to something else that helps you uniquely identify the specific row being clicked on.
This article brings the solution with DataContextProxy. Applying this solution makes possible to write a button code like Austin Lamb's answer.
The command binding using the Event Trigger looks fine (This is how i always do it),
But I suspect that your command is never assigned to (You are using Automatic Properties)
I usually do it like this:
private ViewModelCommand viewOrganizationCommand;
public ViewModelCommand ViewOrganizationCommand
{
get
{
if (viewOrganizationCommand == null)
viewOrganizationCommand = new ViewModelCommand(Action, CanDoIt);
return viewOrganizationCommand;
}
}
try setting you Button's DataContext to the StackPanel and set the Command and CommandParameter of the Button.
<datagrid:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal"
VerticalAlignment="Center" DataContext="{StaticResource XDataContext}">
<Button x:Name="button" Content="View" Margin="5" Command="{Binding ViewOrganizationCommand}" CommandParameter="{Binding ElementName=dtgOrganizations, Path=SelectedItem}" >
</Button>
</StackPanel>
</DataTemplate>
</datagrid:DataGridTemplateColumn.CellTemplate>
I solved this problem by use EventToCommand behavior in MVVMLight Toolkit
Each row of the DataGrid has it's DataContext set to that object. If the ItemSource for the grid is an ObservableCollection, each row's DataContext is the Organization object.
There are two ways to handle this.
Create a wrapping or extension ViewModel that exposes the command. Then the command should fire.Here is some psuedo code.
public class OrganizationExtensionViewModel
{
<summary>
/// Private currentOrginization property.
/// </summary>
private Organization currentOrginization;
public Organization CurrentOrganization
{
get
{
return this.currentOrginization;
}
set
{
if (this.currentOrginization != value)
{
this.currentOrginization = value;
this.RaisePropertyChanged("CurrentOrganization");
}
}
}
public ViewModelCommand ViewOrganizationCommand { get; set; }
public OrganizationExtensionViewModel(Organization o)
{
this.CurrentOrganization = o;
this.ViewOrganizationCommand = new ViewModelCommand(this.ViewOrgnaizationClicked);
}
}
Define the ViewModel in the xaml as a StaticResource and refer to it as the binding path.
...
In the grid
<Button x:Name="button" Content="View" Margin="5" Command="{Binding ViewOrganizationCommand, Source={StaticResource viewModel}}" />

WPF: ComboBoxes in ListBox and concurrency

I have code like this:
<ListBox ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock>Some Other Stuff Here</TextBlock>
<ComboBox ItemsSource="{Binding}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The problem is, every time the outside ListBox.SelectedItem gets changed, the ComboBoxes inside it would change their SelectedIndex to -1. Which means if I click "Some Other Stuff Here" (unless the ListBoxItem it is in is selected), all the comboboxes' selection get cleared.
How do I overcome this? Thx!
Presumably your combobox is bound to something like an ObservableCollection - try exposing an instance of ICollectionView instead:
class DataSource
{
// ...
public ObservableCollection<string> MyData { get; private set; }
public ICollectionView MyDataView
{
get
{
return CollectionViewSource.GetDefaultView(this.MyData);
}
}
}
You can then bind your combobox with:
<ComboBox ItemsSource="{Binding MyDataView}" IsSynchronizedWithCurrentItem="True" />
This means that the 'selected item' for each data source is stored in the ICollectionView object instead of within the combobox, which should mean that it is persisted when the ListBox SelectedItem changes

Resources