I have a list box in my WPF application. I know how to use the selectionchanged event. However I am trying to follow the MVVM design. However I am not sure how to do this.
I have done this for a button however not sure if I can do the same thing?
<Button Grid.Column="0" Name="buttImport"
Content="Import File"
Command="{Binding CommandButtImport}"
Style="{StaticResource ButtonTemplate}"/>
public class ViewModel : INotifyPropertyChanged
{
// for the button that imports the orders file
public ICommand CommandButtImport { get; set; }
public ViewModel()
{
CommandButtImport = new MyCommands(
ExecuteCommandButtImport,
CanExecuteCommandButtImport);
}
private bool CanExecuteCommandButtImport(object parameter)
{
return true;
}
// import button
private void ExecuteCommandButtImport(object parameter)
{
// some code
}
}
EDIT Please ignore code above
I have changed my code so have reposted below what I currently have. I have a strange issue. The XAML - Main Code contains the code for my datagrid. The block below App - XAML contains the styling for most of my app, but is just a snipet.
Also
Code Line added beneath my datagrid in XAML - Main Code for testing purposes.
<ListBox ItemsSource="{Binding SelectedItem.DuplicateSecurities, ElementName=dataGridOrders}"
SelectedItem="{Binding SelectedItem.Security, ElementName=dataGridOrders}"/>
My datagrid loads fine. When I click on a row, the row expands to show a list of Securities. The issue I have is that in this listbox when I click on an item nothing happens. However the Listbox which I added beneath my datagrid for testing purposes does work. For example I click on one of the items and my row is updated, also the listbox in my row detail becomes selected. Its very strange why the listbox in my rowdetail doesn't work but the one beneath my datagrid does. Any ideas?
XAML - Main Code
<StackPanel>
<!-- The data grid to display orders-->
<DataGrid DataContext="{Binding OrderBlock}"
x:Name="dataGridOrders"
ItemsSource="{Binding Orders}"
Style="{StaticResource DataGridTemplate}"
ColumnHeaderStyle="{StaticResource DG_ColumnHeader}"
RowHeaderStyle="{StaticResource DG_RowHeader}"
RowStyle="{StaticResource DG_Row}"
CellStyle="{StaticResource DG_Cell}"
RowDetailsTemplate="{StaticResource DG_RowDetail}"
AutoGenerateColumns="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Silver"
RowHeaderWidth="30"
Margin="25,5,20,15">
<DataGrid.Columns>
<DataGridComboBoxColumn Header="Action">
<DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.StatusList}"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="SelectedValue" Value="{Binding StatusGood}"/>
</Style>
</DataGridComboBoxColumn.ElementStyle>
<DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DataGrid}}, Path=DataContext.StatusList}"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="SelectedValue" Value="{Binding StatusGood}"/>
</Style>
</DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
<DataGridTextColumn Header="Fund" Binding="{Binding Account}" IsReadOnly="True"/>
<DataGridTextColumn Header="Security ID" Binding="{Binding Security.ID}" IsReadOnly="True"/>
<DataGridTextColumn Header="ThinkFolio Security ID" Binding="{Binding ThinkFolioSecurityID}" IsReadOnly="True"/>
<DataGridTextColumn Header="Security Name" Binding="{Binding Security.Name}" IsReadOnly="True"/>
<DataGridTextColumn Header="Buy/Sell" Binding="{Binding TransType}" IsReadOnly="True"/>
<DataGridTextColumn Header="Quantity" Binding="{Binding OrderQunatity, StringFormat=\{0:N0\}}" IsReadOnly="False"/>
<DataGridTextColumn Header="Currency" Binding="{Binding BuyCurrency}" IsReadOnly="False"/>
<DataGridTextColumn Header="Manager" Binding="{Binding FundManager}" IsReadOnly="True"/>
<DataGridTextColumn Header="Order Reason" Binding="{Binding OrderReason}" IsReadOnly="True"/>
<DataGridTextColumn Header="Reject Reason" Binding="{Binding RejectReason}" IsReadOnly="True" Width="*"/>
</DataGrid.Columns>
</DataGrid>
<ListBox ItemsSource="{Binding SelectedItem.DuplicateSecurities, ElementName=dataGridOrders}" SelectedItem="{Binding SelectedItem.Security, ElementName=dataGridOrders}"/>
</StackPanel>
App XAML
<!-- Row Detail Template for Data Grid -->
<DataTemplate x:Key="DG_RowDetail">
<Grid x:Name="RowDetailGrid"
Margin="5"
HorizontalAlignment="Left">
<Border HorizontalAlignment="Left"
VerticalAlignment="Top"
Width="500"
Height="80"
CornerRadius="5">
<Border.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
<GradientStop Offset="0" Color="Transparent"/>
<GradientStop Offset="1" Color="Transparent"/>
</LinearGradientBrush>
</Border.Background>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="2.5*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0"
Grid.ColumnSpan="3"
Margin="5,0,0,5"
HorizontalAlignment="Left"
FontSize="12"
FontWeight="Bold"
Foreground="Black"
Text="Select Security Identifier">
</TextBlock>
<ListBox Grid.Row="1" Grid.ColumnSpan="3" Name="lbIdentifier" ItemsSource="{Binding DuplicateSecurities}" SelectedItem="{Binding Security}"
SelectionMode="Single" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=ID}" FontSize="10" HorizontalAlignment="Left" Margin="5,0,0,0"/>
<TextBlock Grid.Column="1" Text="{Binding Path=Name}" FontSize="10" HorizontalAlignment="Left" Margin="5,0,0,0"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Border>
</Grid>
</DataTemplate>
ViewModel
public class ViewModel : INotifyPropertyChanged
{
public ICommand CommandButtImport { get; set; } // for the button that imports the orders file
public ICommand CommandButtSend { get; set; } // the button where the user sends the orders in our data grid to thinkFolio
public ICommand CommandButtExit { get; set; } // exit application
private QoEMain _QoEManager; // manages the Model
public QoEMain QoEManager { get { return this._QoEManager; } set { _QoEManager = value; } }
private OrderBlocks _orderBlock; // order block - contains all the order information
public OrderBlocks OrderBlock
{
get
{
return this._orderBlock;
}
set
{
this._orderBlock = value;
OnPropertyChanged("OrderBlock");
}
}
}
OrderBlocks Class which contains the other classes
public class OrderBlocks : INotifyPropertyChanged
{
private List<Order> _orders;
[XmlElement("tF_Transactions")]
public List<Order> Orders { get { return _orders; } set { _orders = value; OnPropertyChanged("Orders"); } }
}
Orders Class
public class Order : INotifyPropertyChanged
{
Security security;
public Security Security
{
get { return security; }
set { security = value; OnPropertyChanged("Security"); }
}
List<Security> duplicateSecurities;
public List<Security> DuplicateSecurities
{
get { return duplicateSecurities; }
set { duplicateSecurities = value; OnPropertyChanged("DuplicateSecurities"); }
}
Security Class
public class Security : INotifyPropertyChanged
{
private string _id;
public string ID
{
get
{
return _id;
}
set
{
_id = value;
OnPropertyChanged("ID");
}
}
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
OnPropertyChanged("Name");
}
}
public Security() { }
public Security(string newID, string newName)
{
ID = newID;
Name = newName;
}
Edit - My code now works please see the code snippet below that works for me
<DataGrid Grid.Row="1" Grid.Column="0"
ItemsSource="{Binding SelectedItem.DuplicateSecurities, ElementName=dataGridOrders}"
SelectedItem="{Binding SelectedItem.Security, ElementName=dataGridOrders}">
Example of binding ListBox SelectionChanged
Event to command in your ViewModel
<ListBox x:Name="myListBox" ItemsSource="{Binding SomeCollection}">
<ie:Interaction.Triggers>
<ie:EventTrigger EventName="SelectionChanged">
<ie:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}" CommandParameter="{Binding ElementName=myListBox, Path=SelectedItem}"/>
</ie:EventTrigger>
</ie:Interaction.Triggers>
</ListBox >
In your ViewModel
:
public class myViewModel
{
public myViewModel()
{
SelectedItemChangedCommand = new DelegateCommand<object>((selectedItem) =>
{
// Logic goes here
});
}
public List<SomeData> SomeCollection { get; set; }
public DelegateCommand<object> SelectedItemChangedCommand { get; set; }
}
This particular example uses Prism MVVM Framework, but you can apply the same idea with any other MVVM framework you are using as well.
Hope this helps
using SelectionChanged
with MVVM is quite simple:
An approach could be to bind to the SelectedIndex
property of the ListBox
and in the property setter in the VM, act accordingly as it would be triggered whenever the property changes.
Example: Here
In this example whenever the selected index changes, the value of that item is increased by one.
the main bit is:
public int SelectedIndex {
get {
return _selectedIndex;
}
set {
if (_selectedIndex == value) {
return;
}
// At this point _selectedIndex is the old selected item's index
_selectedIndex = value;
// At this point _selectedIndex is the new selected item's index
RaisePropertyChanged(() => SelectedIndex);
}
}
xaml would just be:
<ListBox ItemsSource="{Binding Items}" SelectedIndex="{Binding SelectedIndex}" />
Items
is the collection of items we bind to.
System.Windows.Interactivity.WPF package has been deprecated.
Install Microsoft.Xaml.Behaviors.Wpf package
<ListBox ItemsSource="{Binding ListItems}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedItem}">
<Behaviors:Interaction.Triggers>
<Behaviors:EventTrigger EventName="SelectionChanged">
<Behaviors:InvokeCommandAction Command="{Binding ItemChangedCommand}" />
</Behaviors:EventTrigger>
</Behaviors:Interaction.Triggers>
</ListBox>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With