0

Simple questions can be the hardest sometimes. 3 things I am trying to understand; 1. Allow a selection change within a combobox to help populate items in 2nd combobox. 2. Clear items in 2nd box before populating items. 3. Adding items in 2nd box.

Note that this code worked on my WinForms code, but I am trying to convert it to WPF and understand that code.

Code:

<ComboBox Name="ComboBox_Location" HorizontalAlignment="Left" Margin="170,56,0,0" VerticalAlignment="Top" Width="160">
        <ComboBoxItem Content="Hospital"/>
</ComboBox>
<ComboBox Name="ComboBox_Printer" HorizontalAlignment="Left" Margin="30,131,0,0" VerticalAlignment="Top" Width="300"/>

$ComboBox_Location.add_SelectionChanged{

    switch ($ComboBox_Location.SelectedItem){

        "Hospital"{
            $ComboBox_Printer.Items.Clear();
            $Hospital = Get-Printer -ComputerName \\bmh01-print01 | where {($_.Name -like “*BMH01*”) -and ($_.DeviceType -eq "Print")}
            foreach($Name in $Hospital){
            $ComboBox_Printer.Items.Add("$($Name.name)");
            }
        }
    }

Thank you in advance! And if any of you have a website or cite I could go to to see the specific coding for WPF, any help will be appreciated!

Megamidget3
  • 59
  • 10

1 Answers1

0

why is this question not answered by anyone.Anyway I will do my best to explain you. Hope I am not late to answer this question.

In WPF, we follow MVVM pattern, So there are 3 parts Model, View and ViewModel. In viewmodel, we need to inherit Icommand and create a CommandHandler, so that if there is any button click / Selction changed will sent via this command and the delegated eventhandler will be raised.

The CommandHandler Class

public class CommandHandler : ICommand
{
    private Action<object> _action;
    private bool _canExeute;
    public event EventHandler CanExecuteChanged;

    private bool canExeute
    {
        set
        {
            _canExeute = value;
            CanExecuteChanged(this, new EventArgs());
        }
    }


    public CommandHandler(Action<object> action,bool canExecute)
    {
        _action = action;
        _canExeute = canExecute;
    } 
    public bool CanExecute(object parameter)
    {
        return _canExeute;
    }

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

This CommandHandler will be used in the ViewModel Class, and then the viewmodel will be set as Datacontext to view via XAML.

   public class ViewModelBase : INotifyPropertyChanged
{
    private List<String> _printer = new List<string>();

    private bool _canExecute;

    public ViewModelBase()
    {
        _canExecute = true;
    }

    public List<string> Printers
    {
        get { return _printer; }
        set { _printer = value; }
    }


    private ICommand _SelectedItemChangedCommand;

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }


    public ICommand SelectedItemChangedCommand
    {
        get
        {
            return _SelectedItemChangedCommand ?? (_SelectedItemChangedCommand =
                       new CommandHandler(obj => SelectedItemChangedHandler(obj), _canExecute));
        }
    }


    public void SelectedItemChangedHandler(object param)
    {
        var selectedItem = ((ComboBoxItem)param).Content;
        switch (selectedItem)
        {
            case "Hospital":
                Printers = new List<string>(); //clearing the list;
                                               // Hospital = GetHospital();// - ComputerName \\bmh01 - print01 | where { ($_.Name - like “*BMH01 *”) -and($_.DeviceType - eq "Print")}

// Here I have added data hard coded, you need to call your method and assgin it to printers property.

                Printers.Add("First Floor Printer");
                Printers.Add("Second Floor Printer");
                OnPropertyChanged(nameof(Printers));
                break;
            default:
                Printers = new List<string>();
               break;
        }
    }


}

The ViewModel class is also inheriting INotifyPropertyChanged, where we need to implement the event and raise it. Now we need to raise propertychanged event providing the property name which is changed using assignment. Therefore inside SelectionChangedCommand, we add Printer and then raise PropertyChanged Event by sending the Printers PropertyName in as Parameter.

The View, We can use either Window or UserControl, For this example I have used Window.

View:-

<Window x:Class="Combo2.MainScreen"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

    xmlns:local="clr-namespace:Combo2"
    xmlns:ViewModel="clr-namespace:Combo2.Validate"
    mc:Ignorable="d"
    x:Name="Window1"
    Title="MainScreen" Height="450" Width="800">
<Window.DataContext>
    <ViewModel:ViewModelBase/>
</Window.DataContext>


    <Grid >
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <Label Content="Location" HorizontalAlignment="Left"  Grid.Row="0" VerticalAlignment="Top" Grid.Column="0"/>
        <ComboBox Name="ComboBox_Location" HorizontalAlignment="Left"   VerticalAlignment="Top" Width="160" Grid.Row="0" Grid.Column="1"  >
            <ComboBoxItem Content="Hospital"/>
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectionChanged">
                    <i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}"  CommandParameter="{Binding ElementName=ComboBox_Location, Path=SelectedItem}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>

        </ComboBox>
        <Label Content="Printer Names" HorizontalAlignment="Left"  Grid.Row="1" VerticalAlignment="Top"  Grid.Column="0"/>
        <ComboBox Name="ComboBox_Printer" HorizontalAlignment="Left"  VerticalAlignment="Top" Width="160"  Grid.Row="1" Grid.Column="1" ItemsSource="{Binding Printers}" >

        </ComboBox>


    </Grid>

Now, As in winform we have click or selectionchanged event but in order to keep the designer separate from code, we are not directly coupling it with it. I mean to say write a selection changed event in code behind then we are not making justification to it. For more information click on https://www.tutorialspoint.com/mvvm/mvvm_introduction.htm which will give you more insight into MVVM.

Now if you notice, when there is a selection changed we have binded the Command Property to a Command Property present in the Viewmodel, which is possible using Interaction class.

So where did we link the view and viewmodel that it at the top of the xaml. Here the datacontext is bound to ViewmodelBase class(viewmodel)

<Window.DataContext>
    <ViewModel:ViewModelBase/>
</Window.DataContext>

Now answer to your question

1)Allow a selection change within a combobox to help populate items in 2nd combobox.

The selectionChanged event is called which will call the Command method present in the ViewModelBase and popluate the Printers Property.

<i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}"  CommandParameter="{Binding ElementName=ComboBox_Location, Path=SelectedItem}"/>

Now since the viewmodel is bound to view any change to the property is displayed in the 2nd dropdown. Now that I have cleared and added data in Printers property, when the 1st drop is selected based on the text if matches "Hospital" the printers are added to the Property and displayed in 2nd Drop down.

2) Clear items in 2nd box before populating items

Before adding data in Printers property, it is cleared by instantiating the List, in your case it could be any other class. Now to whether the selected data is Hospital, we need to send the SelectedItem using the Command Parameter , we cast the "param" with ComboBoxItem and got the content.

3) Adding items in 2nd box.

We sure did add the values in Printers property.

Hope this helps you !!

Sats
  • 1,913
  • 1
  • 15
  • 21