Search code examples
c#wpfcombobox

I get combo box selected item only in View Model class but can't use it out of view model class its throw null


here is my Xaml

  <!--Dimension Type Combobox-->
        <ComboBox x:Name="ComboBox" 
                  ItemsSource="{Binding  empList }" 
                  SelectedItem="{Binding  selectedEmployee, Mode=OneWayToSource}"
                  DisplayMemberPath="Name"
                 SelectedIndex="0"

        />


        <!--Buttons-->
        <Grid Margin="20,0,0,0" >
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>


            <Button Grid.Column="1" Content="Ok" Margin="10,20,0,0" 
                    IsDefault="True" Command="{Binding OkCommand}" />

here is my ViewModel. I can use selected item here if I replaced actions.showMessageTest(); with MessageBox.Show($"you select employee {selected.Name}"); I can get the Message.

class ViewModel : INotifyPropertyChanged
{
    private Actions actions;
    private wbCommand _OkCommand ;
    public wbCommand OkCommand
    {
        get { return _OkCommand; }

        set
        {
            _OkCommand = value;
            NotifyPropertyChanged(nameof(OkCommand));
        }
    }



    private ObservableCollection<employee> _empList;

    public ObservableCollection<employee> empList
    {
        get { return _empList; }
        set
        { 
            _empList = value;
            NotifyPropertyChanged(nameof(empList));
        }
    }


    private employee _selectedEmployee;

    public employee selectedEmployee
    {
        get { return _selectedEmployee; }
        set 
        {
            _selectedEmployee = value;
            NotifyPropertyChanged(nameof(selectedEmployee));
        }
    }

    public ViewModel()
    {
        OkCommand = new wbCommand();
        empList = new ObservableCollection<employee>() { new employee { Name = "mahmoud", Id = 2019 }, new employee { Name = "maged", Id = 2017 } };
        ExecuteAction();
    }


    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public void ExecuteAction()
    {
       

        OkCommand.CommandAction = () =>
        {
            actions.showMessageTest();

        };
      

    }
}

here is my WBCommand Class which Implement I command

class wbCommand : ICommand
{

    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }
    public Action CommandAction = () => { };

    public void Execute(object parameter)
    {
        CommandAction();
    }
}

here is my Actions Class which includes what I want to Execute by Button Ok and here the problem: I can't get Selected Item here to Execute Message.

public class Actions : INotifyPropertyChanged
{
    private ViewModel vm;

    private employee _selected;
    public employee selected 
    { 
        get
        {
            return _selected ;
        }

        set
        {
            _selected = value;
            NotifyPropertyChanged(nameof(selected));
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public void showMessageTest()
    {
        selected = vm.selectedEmployee;

        MessageBox.Show($"you select employee {selected.Name}");

    }
}

Solution

  • you didn't initialize vm field in Actions class, vm is always null

    you can for example pass it as constructor argument:

    public class Actions : INotifyPropertyChanged
    {
        private ViewModel vm;
        public Actions(ViewModel vm)
        {
             this.vm = vm;
        }
    }
    

    you also need to initialize actions field in ViewModel class:

    class ViewModel : INotifyPropertyChanged
    {
        private Actions actions;
        public ViewModel ()
        {
             actions = new Actions(this);
        }
    }
    

    it also make sense to check that selected item is not null:

    public void showMessageTest()
    {
        selected = vm.selectedEmployee;
        if (selected != null)
            MessageBox.Show($"you select employee {selected.Name}");
    }