How to get selected item in MVVM-WPF

38,233

Solution 1

Create a Property in the ViewModel for saving the selected User:

public User SelectedUser { get; set; }

Bind SelectedItem of the ListView to this Property:

<ListView Name="UserGrid" ItemsSource="{Binding Users}" SelectedItem="{Binding SelectedUser}">

Now you just have to check if the SelectedUser property is null.

Solution 2

how to pass "Selected item to do these two things"

This usually can be achieved with SelectedSomething property in your view model. This property should be bound to SelectedItem of control.

and to check before closing panel that is there any text in textbox fields or not

This is called "validation". WPF supports validation in several ways, one of them is implementing IDataErrorInfo in your view model. I'd recommend this way, because it is a de facto standard for .NET (it is used in WinForms and ASP .NET as well).

one check to see whether user has selected item or not. If he doesn't select any item and click on "Edit Button" It will show a MessageBox to user to select an item to edit

Again, usually, this being solved with ICommand instance, bound to the button. If ICommand.CanExecute returns false, bound button becomes disabled.

For example, you should check for validation errors in CanExecute for command, bound to Close button, and return false, if there are any errors. Or you should check SelectedSomething property in CanExecute for command, bound to Edit button, and return false, if SelectedSomething == null.

In MVVM world thing becomes easier, if you use RelayCommand/DelegateCommand as the default ICommand implementation.

Update.

A code sample for commands. View model:

public class UserViewModel
{
    public UserViewModel()
    {
        EditCommand = new RelayCommand(EditSelectedUser, () => SelectedUser != null);
    }

    private void EditSelectedUser()
    {
        // some edit code here
    }

    public User SelectedUser { get; set; }
    public ICommand EditCommand { get; private set; }
}

XAML:

<Button Content="Edit" Command="{Binding EditCommand}"/>
Share:
38,233
Zoya Sheikh
Author by

Zoya Sheikh

Updated on November 21, 2020

Comments

  • Zoya Sheikh
    Zoya Sheikh over 3 years

    Hi I am using WPF and MVVM, There is "Edit/Update" Panel in my application it updates selected data in Grid. It is working fine. I want to add one button "Close Button" and "one check to see whether user has selected item or not. If he doesn't select any item and click on "Edit Button" It will show a MessageBox to user to select an item to edit. Thing i am not getting clear is that how to pass "Selected item to do these two things" and to check before closing panel that is there any text in textbox fields or not. User View Model Code:

    public class UserViewModel
    {
        private IList<User> _UsersList;
        public UserViewModel()
        {
            _UsersList = new List<User>
        {
            new User { UserId = 1, FirstName = "Raj", LastName = "Beniwal", City = "Delhi", State = "DEL", Country = "INDIA" },
            new User { UserId = 2, FirstName = "Mark", LastName = "henry", City = "New York", State = "NY", Country = "USA" },
            new User { UserId = 3, FirstName = "Mahesh", LastName = "Chand", City = "Philadelphia", State = "PHL", Country = "USA" },
            new User { UserId = 4, FirstName = "Vikash", LastName = "Nanda", City = "Noida", State = "UP", Country = "INDIA" },
            new User { UserId = 5, FirstName = "Harsh", LastName = "Kumar", City = "Ghaziabad", State = "UP", Country = "INDIA" },
            new User { UserId = 6, FirstName = "Reetesh", LastName = "Tomar", City = "Mumbai", State = "MP", Country = "INDIA" },
            new User { UserId = 7, FirstName = "Deven", LastName = "Verma", City = "Palwal", State = "HP", Country = "INDIA" },
            new User { UserId = 8, FirstName = "Ravi", LastName = "Taneja", City = "Delhi", State = "DEL", Country = "INDIA" }           
        };
    }
    
    public IList<User> Users
    {
        get { return _UsersList; }
        set { _UsersList = value; }           
    }
    
    private ICommand mUpdater;
    
    public ICommand UpdateCommand
    {
        get
        {
            if (mUpdater == null)
            {
                mUpdater = new Updater();
            }
            return mUpdater;
        }
        set
        {
            mUpdater = value;
        }
    }
    
    private class Updater : ICommand
    {
        #region ICommand Members
    
        public bool CanExecute(object parameter)
        {              
            return true;
        }
    
        public event EventHandler CanExecuteChanged;
    
        public void Execute(object parameter)
        {
        }
    
        #endregion
        }
    }
    

    User View Window.Xaml Panel1

    <dxdo:LayoutPanel Caption="Panel1" x:Name="Panel1">
        <Grid Margin="0,0,0,20">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="*" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <ListView Name="UserGrid" Grid.Row="1" Margin="4,178,12,13" ItemsSource="{Binding Users}">
                <ListView.View>
                    <GridView x:Name="grdTest">
                        <GridViewColumn Header="UserId" DisplayMemberBinding="{Binding UserId}" Width="50" />
                        <GridViewColumn Header="First Name" DisplayMemberBinding="{Binding FirstName}" Width="80" />
                        <GridViewColumn Header="Last Name" DisplayMemberBinding="{Binding LastName}" Width="100" />
                        <GridViewColumn Header="City" DisplayMemberBinding="{Binding City}" Width="80" />
                        <GridViewColumn Header="State" DisplayMemberBinding="{Binding State}" Width="80" />
                        <GridViewColumn Header="Country" DisplayMemberBinding="{Binding Country}" Width="100" />
                    </GridView>
                 </ListView.View>
              </ListView>
           </Grid>
    </dxdo:LayoutPanel>
    <dxdo:LayoutPanel x:Name="Panel3">
        <Grid>
            <StackPanel>
                <Button Content="Edit" Height="23" HorizontalAlignment="Left" VerticalAlignment="Top" Width="141" Click="Button_Click_1" />
            </StackPanel>
        </Grid>
    </dxdo:LayoutPanel>
    

    Panel2:

    <dxdo:LayoutPanel Caption="Panel2" x:Name="Panel2">
        <Grid>
            <StackPanel Margin="0,0,0,10">
                <Grid Margin="0,0,0,20">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                        <RowDefinition Height="Auto" />
                    </Grid.RowDefinitions>
                    <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,7,0,0" Name="txtUserId" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=UserGrid, Path=SelectedItem.UserId}" />
                    <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,35,0,0" Name="txtFirstName" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=UserGrid, Path=SelectedItem.FirstName}" />
                    <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,62,0,0" Name="txtLastName" VerticalAlignment="Top" Width="178" Text="{Binding ElementName=UserGrid, Path=SelectedItem.LastName}" />
                    <Label Content="UserId" Grid.Row="1" HorizontalAlignment="Left" Margin="12,12,0,274" Name="label1" />
                    <Label Content="Last Name" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,60,0,0" Name="label2" VerticalAlignment="Top" />
                    <Label Content="First Name" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,35,0,0" Name="label3" VerticalAlignment="Top" />
                    <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,143,0,0" x:Name="txtCity" VerticalAlignment="Top" Width="178" Text="{Binding SelectedItem.City, ElementName=UserGrid}" />
                    <Label Content="Country" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,141,0,0" x:Name="label2_Copy" VerticalAlignment="Top" />
                    <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,88,0,0" x:Name="txtCountry" VerticalAlignment="Top" Width="178" Text="{Binding SelectedItem.Country, ElementName=UserGrid}" />
                    <Label Content="City" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,86,0,0" x:Name="label2_Copy1" VerticalAlignment="Top" />
                    <TextBox Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="80,115,0,0" x:Name="txtSTate" VerticalAlignment="Top" Width="178" Text="{Binding SelectedItem.State, ElementName=UserGrid}" />
                    <Label Content="State" Grid.Row="1" Height="28" HorizontalAlignment="Left" Margin="12,113,0,0" x:Name="label2_Copy2" VerticalAlignment="Top" />
                </Grid>
                <Button Content="Update" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="310,40,0,0" Name="btnUpdate" VerticalAlignment="Top" Width="141" Command="{Binding Path=UpdateCommad}" />
                <Button Content="Close" Grid.Row="1" Height="23" HorizontalAlignment="Right" VerticalAlignment="Top" Width="141" Click="Button_Click_2" />
                <TextBox Width="166" Background="White" Height="33"  HorizontalAlignment="Right" VerticalAlignment="Bottom" Text="{Binding Path=SelectedCustomer.LastName,Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" />    
            </StackPanel>
        </Grid>
    </dxdo:LayoutPanel>    
    

    (If my question is not clear to you plesae ask me. Thank you)

  • AsitK
    AsitK over 10 years
    If you dont want to keep the SelectedItem property in your view model, you can also pass the selected item as the parameter to the command. You can also use the same command to warn then if nothing is selected i.e. parameter passed is null AND process further if parameter is not null.
  • Zoya Sheikh
    Zoya Sheikh over 10 years
    How to check whether it is null or not? where to define this?
  • doerig
    doerig over 10 years
    If(SelectedUser == null) { ShowNoUserSelectedWarning(); }
  • Zoya Sheikh
    Zoya Sheikh over 10 years
    compiler says that SelectedUser it is property but use like variable.
  • Zoya Sheikh
    Zoya Sheikh over 10 years
    @Dennis Thank you for response. how to achieve this Again, usually, this being solved with ICommand instance, bound to the button. If ICommand.CanExecute returns false, bound button becomes disabled Can you please describe me this via code?
  • Stan1k
    Stan1k almost 2 years
    The best MVVM solution I found on my research. Simple and clear.