Reputation: 580
I am just doing some practice on WPF & MVVM forms So far, I have just completed the normal Listbox with data loaded from an array, that when the index changes, it loads other data into textblocks on the form
I would like to change this example however. I want the user to select a field in the listbox, then click a button to display all the other data
So, the form is (usercontrol):
And when someone selects, say Cena, they will see the data on the right filled out.
My code for the .xaml is:
<UserControl x:Class="SuperstarsRoster.RosterView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SuperstarsRoster"
xmlns:WpfToolkit="http://schemas.microsoft.com/wpf/2008/toolkit"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="600">
<UserControl.DataContext>
<local:RosterViewModel/>
</UserControl.DataContext>
<Grid x:Name="LayoutRoot" Background="White" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!--SelectedItem="{Binding SelectedPerson}"-->
<ListBox Grid.Column="0" Margin="0"
ItemsSource="{Binding RosterList}"
DisplayMemberPath="Name"
Name="lstRoster"
Height="250"
VerticalAlignment="Top"/>
<Button Content="Exit" Height="23" HorizontalAlignment="Left" VerticalAlignment="Bottom" Name="btnExit" Width="150" Command="{Binding ButtonCommand}" CommandParameter="Hai" />
<Grid x:Name="PersonDetails" Grid.Column="1" DataContext="{Binding SelectedPerson}" Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="150"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="Person Details" FontSize="15"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Name"/>
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Name,Mode=TwoWay}"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Brand"/>
<TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Brand,Mode=TwoWay}"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Type"/>
<TextBlock Grid.Row="3" Grid.Column="1" Text="{Binding Type,Mode=TwoWay}"/>
<Button Grid.Row="4" Content="Choose" Height="23" HorizontalAlignment="Left" VerticalAlignment="Bottom" Name="btnChoose" Width="90" Command="{Binding ChooseCommand}" CommandParameter="{Binding ElementName=lstRoster,Path=SelectedPerson}" />
</Grid>
</Grid>
my problem is the Show button:
<Button Grid.Row="4" Content="Choose" Height="23" HorizontalAlignment="Left" VerticalAlignment="Bottom" Name="btnChoose" Width="90" Command="{Binding ChooseCommand}" CommandParameter="{Binding ElementName=lstRoster,Path=SelectedPerson}" />
I don't know what to do here. I don't know if the CommandParameters should be empty, or have something in it.
My ViewModel code is:
#region Show Button
private ICommand m_ShowCommand;
public ICommand ShowCommand
{
get
{
return m_ShowCommand;
}
set
{
m_ShowCommand = value;
}
}
public void Selected(object obj)
{
RaisePropertyChanged("SelectedPerson");
}
#endregion
I have a feeling my Selected is the incorrect piece of code. On the ViewModel code there is also:
#region Roster Details
public ObservableCollection<Roster> rosterList;
public Roster selectedPerson;
public RosterViewModel()
{
ButtonCommand = new RelayCommand(new Action<object>(ShowMessage));
ShowCommand = new RelayCommand(new Action<object>(Selected));
rosterList = new ObservableCollection<Roster>()
{
new Roster(){Name="Batista", Brand="Smackdown!", Type="Heel"},
new Roster(){Name="The Rock", Brand="RAW", Type="Face"},
new Roster(){Name="John Cena", Brand="RAW", Type="Face"},
new Roster(){Name="Randy Orton", Brand="Smackdown!", Type="Heel"}
};
RaisePropertyChanged("SelectedPerson");
}
#endregion
With the ShowCommand being the button event, but I don't know what to put here.
Ideally, user selects Cena, clicks show, and the textblocks will fill with the data from the array.
My RelayCommand class (the default for all button clicks) looks like so:
class RelayCommand : ICommand
{
private Action<object> _action;
public RelayCommand(Action<object> action)
{
_action = action;
}
#region ICommand Members
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_action(parameter);
}
#endregion
Should there be something more here? Or in the ViewModel?
I'm using MVVM, so there is no code in my code behind class.
The Exit button works, that's why I know the commands will work.
EDIT
I changed some of the code now. Firstly, the show button was sitting in a grid that had a datacontext setting. That was taken out. Next, both buttons share the same command (ButtonCommand), but both have different parameters. Exit is "Exit", and choose is "Hai"
In the ViewModel code, the following was added and changed
public string Name { get; set; }
public string Brand { get; set; }
public string Type { get; set; }
#region Button Work
private ICommand m_ButtonCommand;
public ICommand ButtonCommand
{
get
{
return m_ButtonCommand;
}
set
{
m_ButtonCommand = value;
}
}
public void DoAction(object obj)
{
if (obj.ToString() == "Hai")
{
if (selectedPerson != null)
{
this.Name = selectedPerson.Name;
this.Brand = selectedPerson.Brand;
this.Type = selectedPerson.Type;
RaisePropertyChanged(null);
}
}
if (obj.ToString() == "Exit")
{
MessageBox.Show("This program will now close");
Environment.Exit(0);
}
}
#endregion
This way, data is set and I can populate the fields when wanted.
Along with initializing it first
public RosterViewModel()
{
ButtonCommand = new RelayCommand(new Action<object>(DoAction));
So, it works now.
Upvotes: 0
Views: 4871
Reputation: 6415
You have a couple of choices really:
(1) Have a VM property that is bound to the SelectedItem
of your ListBox
, and then you don't need to send any parameters with your button command ... you can just perform your ChooseCommand
on the currently SelectedItem
(as known by you VM).
or
(2) Pass in the SelectedItem
as a parameter on your command, like this ...
<Button Grid.Row="4" Content="Choose" Height="23" HorizontalAlignment="Left"
VerticalAlignment="Bottom" Name="btnChoose" Width="90"
Command="{Binding ChooseCommand}"
CommandParameter="{Binding ElementName=MyListBox,Path=SelectedItem}" />
Note that you will need to give your ListBox a name (x:Name="MyListBox") and that your CommandParameter is referring to that ListBox, and its SelectedItem property.
Upvotes: 1