xceedsoftware / wpftoolkit

All the controls missing in WPF. Over 1 million downloads.
Other
3.9k stars 878 forks source link

Setting ``Wizard.CurrentPage`` in DataTrigger does not work #1744

Closed 5cover closed 1 year ago

5cover commented 1 year ago

I have a wizard with a page (Page1) that starts a task when the Enter event is recieved. I want to go to the next page (Page2) automatically when the task is done.

Considering that I use the MVVM architecture for pages, I update the "Finished" property of the view model of Page1 accordingly:

public sealed class Page1ViewModel : ViewModel
{
    private bool _finished;

    public Page1ViewModel()
    {
        Start = new AsyncRelayCommand(PerformTask);
    }

    public bool Finished
    {
        get => _finished;
        set
        {
            _finished = value;
            OnPropertyChanged();
        }
    }

    public IAsyncRelayCommand Start { get; }

    private async Task PerformTask()
    {
        for (int i = 0; i < 100; ++i)
        {
            await Task.Delay(20);
        }
        Finished = true;
    }
}

I use a DataTrigger in the Wizard definition to update the current page when Finish is set to True

<xctk:Wizard>

    <!-- Create the pages and their ViewModels -->
    <xctk:Wizard.Resources>
      <viewModel:Page1ViewModel x:Key="Page1ViewModel"/>
      <viewModel:Page2ViewModel x:Key="Page2ViewModel"/>

      <view:Page1 x:Key="Page1" DataContext="{StaticResource Page1ViewModel}"/>
      <view:Page2 x:Key="Page2" DataContext="{StaticResource Page2ViewModel}"/>
    </xctk:Wizard.Resources>

    <!-- Add the pages to the wizard -->
    <xctk:WizardPage/> <!-- Intro page -->
    <StaticResource ResourceKey="Page1"/>
    <StaticResource ResourceKey="Page2"/>

    <xctk:Wizard.Style>
        <Style TargetType="xctk:Wizard">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Finished, Source={StaticResource Page1ViewModel}}" Value="True">
                    <Setter Property="CurrentPage" Value="{DynamicResource Page2}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </xctk:Wizard.Style>
</xctk:Wizard>

If I replace the CurrentPage setter with another setter, it works, so the trigger works.

{DynamicResource Page2} returns a valid page, because it works if I do it in codebehind, like this

wizard.CurrentPage = (WizardPage)wizard.Resources["Page2"];

When the CurrentPage setter is executed, nothing happens and Page1 is still displayed.

XceedBoucherS commented 1 year ago

Hi,

Thank you for reporting this. This issue will be fixed in the next release : v4.6.

In the meantime, here's a fix you can implement. Go in file : Xceed.Wpf.Toolkit/Wizard/Implementation/Wizard.cs in method : OnItemsChanged and replace CurrentPage = Items[ 0 ] as WizardPage; with this.SetCurrentValue( Wizard.CurrentPageProperty, Items[ 0 ] as WizardPage );

This will not ovewrite the CurrentPage property when at startup the CurrentPage is null. Thanks