Search code examples
c#xamlmvvmwin-universal-apptemplate10

Binding MVVM Command to TimePicker control in UWP


I'm using a TimePicker control on a XAML page and try to react on changes in the corresponding ViewModel. I added the Xaml.Interactivity and Xaml.Interactivity.Core namespace to my page in order to use the Behaviors SDK to trigger the command once the TimeChanged event is called.

<!-- XAML Namespaces -->
xmlns:interact="using:Microsoft.Xaml.Interactivity"
xmlns:interactcore="using:Microsoft.Xaml.Interactions.Core"

<TimePicker x:Name="TestTimePicker" ClockIdentifier="24HourClock" Time="0">
    <interact:Interaction.Behaviors>
        <interactcore:EventTriggerBehavior EventName="TimeChanged">
            <interactcore:InvokeCommandAction Command="{Binding DataContext.TimeChangedCommand}" CommandParameter="{Binding ElementName=TestTimePicker, Path=Time}" />
        </interactcore:EventTriggerBehavior>
    </interact:Interaction.Behaviors>
</TimePicker>

For the code in my ViewModel I use ViewModelBase and DelegateCommand from Template10.

public DelegateCommand<TimeSpan> StartTimeChangedCommand { get; set; }

public TestViewModel()
{
    ...
    TimeChangedCommand = new DelegateCommand<TimeSpan>(TimeChangedAction);
    ...
}

private void TimeChangedAction(TimeSpan obj)
{
    //do something with obj
}

Once the Page is Initialized a InvalidOperationException with the following message gets thrown.

Adding or removing event handlers dynamically is not supported on WinRT events.

Solution

  • Thank you for the discussion @Archana. I found a work-around for my problem. Instead of using Binding to connect with a Command in the ViewModel I am now using compiled binding x:Bind to directly connect the event with a handler in the ViewModel.

    I updated the TimePicker control

    <TimePicker x:Name="TestTimePicker" ClockIdentifier="24HourClock" Time="{x:Bind ViewModel.TestTime, Mode=TwoWay}" TimeChanged="{x:Bind ViewModel.TestTimeChangedEvent}" />
    

    And the code in the ViewModel

    public void TestTimeChangedEvent (object sender, TimePickerValueChangedEventArgs e)
    {
        TestTime = e.NewTime;
    }