2

I am new in MVVM/WPF, I was studying web examples for last two weeks but still I couldn't find out how to deal with following thing:

I am working on some sort of "defect inserting software" for our manufacturing department in company. User can "create new record", then based on user's choice different UserControls with different Questions/RadioButtons/ComboBoxes are displayed.

I inspired with great article about Internationalized Wizard , but the wizard in this example is really simple and straightforward.

Following code creates my first wizard steps:

 void CreatePages()
 {
      var welcomePage = new WelcomePageViewModel();
      var settings = new SettingsViewModel();
      var cellScrap = new WizardChooseCellScrapGradeViewModel(this.CellScrap);
      var manufacturer = new WizardChooseManufacturerViewModel(this.CellScrap);

      var pages = new List<WizardPageViewModelBase>(); 

      pages.Add(welcomePage);
      pages.Add(settings);
      pages.Add(cellScrap);
      pages.Add(manufacturer);

      _pages = new ReadOnlyCollection<WizardPageViewModelBase>(pages);
 }

Now when user chooses manufacturer A, program should ask him to fill data in usercontrol_1, if he chooses manufacturer B, then usercontrol_2 will be shown.

Whats the best practice to do this? I suppose I cannot use ReadOnlyCollection for this, any better idea?

Yaroslav
  • 6,476
  • 10
  • 48
  • 89
dellasp
  • 23
  • 2

2 Answers2

0

You can find the answer on the following links

Community
  • 1
  • 1
Furqan Safdar
  • 16,260
  • 13
  • 59
  • 93
0

I typically use a ContentControl with the ContentControl.Template being set to whatever Template is needed by a DataTrigger that based on some bound value

<DataTemplate x:Key="ManufacturerAView" TargetType="{x:Type local:WizardPageViewModelBase}">
    <TextBlock Text="I'm Manufacturer A" />
</DataTemplate>

<DataTemplate x:Key="ManufacturerBView" TargetType="{x:Type local:WizardPageViewModelBase}">
    <TextBlock Text="I'm Manufacturer B" />
</DataTemplate>

<ContentControl Content="{Binding }">
    <ContentControl.Style>
        <Style TargetType="{x:Type ContentControl}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Manufacturer}" Value="A">
                    <Setter Property="ContentTemplate" Value="{StaticResource ManufacturerAView}" />
                </DataTrigger>
                <DataTrigger Binding="{Binding Manufacturer}" Value="B">
                    <Setter Property="ContentTemplate" Value="{StaticResource ManufacturerBView}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ContentControl.Style>
</ContentControl>

This will only work if your ManufacturerViewModel is the same regardless of which Manufacturer is selected.

If it's different, I would attach a PropertyChange event to the ChooseManufacturerViewModel that would add a specific ManufacturerViewModel to the collection whenever the SelectedManufacturer property changes.

manufacturer.PropertyChanged += ChooseManufacturer_PropertyChanged;
pages.Add(manufacturer);

....

void ChooseManufacturer_PropertyChanged(object src, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "SelectedManufacturer")
    {
        switch ((WizardChooseManufacturerViewModel)src).SelectedManufacturer)
        {
            // You'll want to check any existing ManufactorerViewModels 
            // and remove them as well if needed
            case "A":
                Pages.Add(new ManufacturerAViewModel);
                break;

            case "B":
                Pages.Add(new ManufacturerBViewModel);
                break;
        }
    }
}

For the UI to be correctly notified that the new page has been added, you'll want to make Pages of type ObservableCollection<WizardPageViewModelBase> instead of a ReadOnlyCollection

Rachel
  • 130,264
  • 66
  • 304
  • 490