ContentDialog ignoring CanExecute

Alex Oh 96 Reputation points
2020-03-09T14:57:27.457+00:00

https://social.msdn.microsoft.com/Forums/windowsapps/en-US/6d5d6fd9-5f03-4cb6-b6c0-19ca01ddaab8/uwpcontentdialog-buttons-do-not-respect-canexecute

https://stackoverflow.com/questions/42439073/uwp-mvvm-contentdialog-with-enabled-primary-button-when-canexecute-is-false

https://stackoverflow.com/questions/25826892/contentdialog-do-not-subscribe-to-icommand-canexecutechanged

As you can see, this has been a problem since 2014. I'm wondering if there is a good reason for why ContentDialog button commands ignore CanExecute changed result, and fails to disable buttons.

The following are the only times that CanExecute is called:

  1. After content dialog is rendered AND only after primary button is pressed.

The issue with this is that by the time you press the button, the dialog closes and it doesn't matter if the button is disabled/enabled now.

The other issue is that the command assigned to PrimaryButtonCommand will never call CanExecute even after calling RaiseCanExecuteChanged() directly.

This seems like a bug, but seeing it hasn't been changed since '14, I'm wondering if this design is intentional. In addition to any suggested workarounds (none of the above links seem to solve the issue or are too specific to an implementation), I'm hoping this will get noticed by a development team.

------------------------------------------

Working on UWP, Windows 10 v.1903

Universal Windows Platform (UWP)
{count} votes

1 answer

Sort by: Most helpful
  1. Fay Wang - MSFT 5,191 Reputation points
    2020-03-10T03:26:16.767+00:00

    Hello,

    ​Welcome to our Microsoft Q&A platform!

    From the style of ContentDialog, there is a Button named PrimaryButton which represents PrimaryButton. It has bound Content, IsEnabled property, etc, but doesn't bind Command property, it should be why CanExecute has no effect. So you can use TemplateBinding to bind PrimaryButtonCommand with Command. And do the same behaviors for SecondaryButton and CloseButton.

    .xaml:

    <Page.Resources>  
            <Style TargetType="ContentDialog" x:Key="MyStyle">  
                <Setter Property="Foreground" Value="{ThemeResource ContentDialogForeground}" />  
                <Setter Property="Background" Value="{ThemeResource ContentDialogBackground}" />  
                <Setter Property="BorderBrush" Value="{ThemeResource ContentDialogBorderBrush}" />  
                <Setter Property="IsTabStop" Value="False" />  
                <Setter Property="Template">  
                    <Setter.Value>  
                        <ControlTemplate TargetType="ContentDialog">  
                            <Border x:Name="Container">  
                                <VisualStateManager.VisualStateGroups>  
                                    <VisualStateGroup x:Name="DialogShowingStates">  
                                        <VisualStateGroup.Transitions>  
                                            <VisualTransition To="DialogHidden">  
                                                <Storyboard>  
                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Visibility">  
                                                        <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible" />  
                                                    </ObjectAnimationUsingKeyFrames>  
                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="IsHitTestVisible">  
                                                        <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="False" />  
                                                    </ObjectAnimationUsingKeyFrames>  
                                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleX">  
                                                        <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.0" />  
                                                        <SplineDoubleKeyFrame KeyTime="0:0:0.5" KeySpline="0.1,0.9 0.2,1.0" Value="1.05" />  
                                                    </DoubleAnimationUsingKeyFrames>  
                                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleY">  
                                                        <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.0" />  
                                                        <SplineDoubleKeyFrame KeyTime="0:0:0.5" KeySpline="0.1,0.9 0.2,1.0" Value="1.05" />  
                                                    </DoubleAnimationUsingKeyFrames>  
                                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Opacity">  
                                                        <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.0" />  
                                                        <LinearDoubleKeyFrame KeyTime="0:0:0.083" Value="0.0" />  
                                                    </DoubleAnimationUsingKeyFrames>  
                                                </Storyboard>  
                                            </VisualTransition>  
                                            <VisualTransition To="DialogShowing">  
                                                <Storyboard>  
                                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Visibility">  
                                                        <DiscreteObjectKeyFrame KeyTime="0:0:0" Value="Visible" />  
                                                    </ObjectAnimationUsingKeyFrames>  
                                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleX">  
                                                        <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.05" />  
                                                        <SplineDoubleKeyFrame KeyTime="0:0:0.5" KeySpline="0.1,0.9 0.2,1.0" Value="1.0" />  
                                                    </DoubleAnimationUsingKeyFrames>  
                                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="ScaleTransform" Storyboard.TargetProperty="ScaleY">  
                                                        <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="1.05" />  
                                                        <SplineDoubleKeyFrame KeyTime="0:0:0.5" KeySpline="0.1,0.9 0.2,1.0" Value="1.0" />  
                                                    </DoubleAnimationUsingKeyFrames>  
                                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Opacity">  
                                                        <DiscreteDoubleKeyFrame KeyTime="0:0:0" Value="0.0" />  
                                                        <LinearDoubleKeyFrame KeyTime="0:0:0.167" Value="1.0" />  
                                                    </DoubleAnimationUsingKeyFrames>  
                                                </Storyboard>  
                                            </VisualTransition>  
                                        </VisualStateGroup.Transitions>  
                                        <VisualState x:Name="DialogHidden" />  
                                        <VisualState x:Name="DialogShowing">  
                                            <VisualState.Setters>  
                                                <Setter Target="LayoutRoot.Visibility" Value="Visible" />  
                                                <Setter Target="BackgroundElement.TabFocusNavigation" Value="Cycle" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                        <VisualState x:Name="DialogShowingWithoutSmokeLayer">  
                                            <VisualState.Setters>  
                                                <Setter Target="LayoutRoot.Visibility" Value="Visible" />  
                                                <Setter Target="LayoutRoot.Background" Value="{x:Null}" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                    </VisualStateGroup>  
                                    <VisualStateGroup x:Name="DialogSizingStates">  
                                        <VisualState x:Name="DefaultDialogSizing" />  
                                        <VisualState x:Name="FullDialogSizing">  
                                            <VisualState.Setters>  
                                                <Setter Target="BackgroundElement.VerticalAlignment" Value="Stretch" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                    </VisualStateGroup>  
                                    <VisualStateGroup x:Name="ButtonsVisibilityStates">  
                                        <VisualState x:Name="AllVisible" />  
                                        <VisualState x:Name="NoneVisible">  
                                            <VisualState.Setters>  
                                                <Setter Target="CommandSpace.Visibility" Value="Collapsed" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                        <VisualState x:Name="PrimaryVisible">  
                                            <VisualState.Setters>  
                                                <Setter Target="PrimaryButton.(Grid.Column)" Value="2" />  
                                                <Setter Target="PrimaryButton.(Grid.ColumnSpan)" Value="2" />  
                                                <Setter Target="PrimaryButton.Margin" Value="2,0,0,0" />  
                                                <Setter Target="SecondaryButton.Visibility" Value="Collapsed" />  
                                                <Setter Target="CloseButton.Visibility" Value="Collapsed" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                        <VisualState x:Name="SecondaryVisible">  
                                            <VisualState.Setters>  
                                                <Setter Target="SecondaryButton.(Grid.Column)" Value="2" />  
                                                <Setter Target="SecondaryButton.(Grid.ColumnSpan)" Value="2" />  
                                                <Setter Target="SecondaryButton.Margin" Value="2,0,0,0" />  
                                                <Setter Target="PrimaryButton.Visibility" Value="Collapsed" />  
                                                <Setter Target="CloseButton.Visibility" Value="Collapsed" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                        <VisualState x:Name="CloseVisible">  
                                            <VisualState.Setters>  
                                                <Setter Target="CloseButton.(Grid.Column)" Value="2" />  
                                                <Setter Target="CloseButton.(Grid.ColumnSpan)" Value="2" />  
                                                <Setter Target="CloseButton.Margin" Value="2,0,0,0" />  
                                                <Setter Target="PrimaryButton.Visibility" Value="Collapsed" />  
                                                <Setter Target="SecondaryButton.Visibility" Value="Collapsed" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                        <VisualState x:Name="PrimaryAndSecondaryVisible">  
                                            <VisualState.Setters>  
                                                <Setter Target="PrimaryButton.(Grid.ColumnSpan)" Value="2" />  
                                                <Setter Target="SecondaryButton.(Grid.Column)" Value="2" />  
                                                <Setter Target="SecondaryButton.(Grid.ColumnSpan)" Value="2" />  
                                                <Setter Target="SecondaryButton.Margin" Value="2,0,0,0" />  
                                                <Setter Target="CloseButton.Visibility" Value="Collapsed" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                        <VisualState x:Name="PrimaryAndCloseVisible">  
                                            <VisualState.Setters>  
                                                <Setter Target="PrimaryButton.(Grid.ColumnSpan)" Value="2" />  
                                                <Setter Target="CloseButton.(Grid.Column)" Value="2" />  
                                                <Setter Target="CloseButton.(Grid.ColumnSpan)" Value="2" />  
                                                <Setter Target="CloseButton.Margin" Value="2,0,0,0" />  
                                                <Setter Target="SecondaryButton.Visibility" Value="Collapsed" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                        <VisualState x:Name="SecondaryAndCloseVisible">  
                                            <VisualState.Setters>  
                                                <Setter Target="SecondaryButton.(Grid.Column)" Value="0" />  
                                                <Setter Target="SecondaryButton.(Grid.ColumnSpan)" Value="2" />  
                                                <Setter Target="SecondaryButton.Margin" Value="0,0,2,0" />  
                                                <Setter Target="CloseButton.(Grid.Column)" Value="2" />  
                                                <Setter Target="CloseButton.(Grid.ColumnSpan)" Value="2" />  
                                                <Setter Target="CloseButton.Margin" Value="2,0,0,0" />  
                                                <Setter Target="PrimaryButton.Visibility" Value="Collapsed" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
      
                                    </VisualStateGroup>  
                                    <VisualStateGroup x:Name="DefaultButtonStates">  
                                        <VisualState x:Name="NoDefaultButton" />  
                                        <VisualState x:Name="PrimaryAsDefaultButton">  
                                            <VisualState.Setters>  
                                                <Setter Target="PrimaryButton.Style" Value="{StaticResource AccentButtonStyle}" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                        <VisualState x:Name="SecondaryAsDefaultButton">  
                                            <VisualState.Setters>  
                                                <Setter Target="SecondaryButton.Style" Value="{StaticResource AccentButtonStyle}" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                        <VisualState x:Name="CloseAsDefaultButton">  
                                            <VisualState.Setters>  
                                                <Setter Target="CloseButton.Style" Value="{StaticResource AccentButtonStyle}" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
      
                                    </VisualStateGroup>  
                                    <VisualStateGroup x:Name="DialogBorderStates">  
                                        <VisualState x:Name="NoBorder" />  
                                        <VisualState x:Name="AccentColorBorder">  
                                            <VisualState.Setters>  
                                                <Setter Target="BackgroundElement.BorderBrush" Value="{ThemeResource SystemControlForegroundAccentBrush}" />  
                                            </VisualState.Setters>  
                                        </VisualState>  
                                    </VisualStateGroup>  
                                </VisualStateManager.VisualStateGroups>  
                                <Grid x:Name="LayoutRoot" Visibility="Collapsed" Background="{ThemeResource SystemControlPageBackgroundMediumAltMediumBrush}">  
                                    <Border x:Name="BackgroundElement"  
                      Background="{TemplateBinding Background}"  
                      FlowDirection="{TemplateBinding FlowDirection}"  
                      BorderThickness="{ThemeResource ContentDialogBorderWidth}"  
                      BorderBrush="{TemplateBinding BorderBrush}"  
                      CornerRadius="{TemplateBinding CornerRadius}"  
                      MinWidth="{ThemeResource ContentDialogMinWidth}"  
                      MaxWidth="{ThemeResource ContentDialogMaxWidth}"  
                      MinHeight="{ThemeResource ContentDialogMinHeight}"  
                      MaxHeight="{ThemeResource ContentDialogMaxHeight}"  
                      HorizontalAlignment="Center"  
                      VerticalAlignment="Center"  
                      RenderTransformOrigin="0.5,0.5">  
                                        <Border.RenderTransform>  
                                            <ScaleTransform x:Name="ScaleTransform" />  
                                        </Border.RenderTransform>  
                                        <Grid x:Name="DialogSpace" Padding="{ThemeResource ContentDialogPadding}">  
                                            <Grid.RowDefinitions>  
                                                <RowDefinition Height="*" />  
                                                <RowDefinition Height="Auto" />  
                                            </Grid.RowDefinitions>  
                                            <ScrollViewer x:Name="ContentScrollViewer"  
                          HorizontalScrollBarVisibility="Disabled"  
                          VerticalScrollBarVisibility="Disabled"  
                          ZoomMode="Disabled"  
                          Margin="{ThemeResource ContentDialogContentScrollViewerMargin}"  
                          IsTabStop="False">  
                                                <Grid>  
                                                    <Grid.RowDefinitions>  
                                                        <RowDefinition Height="Auto" />  
                                                        <RowDefinition Height="*" />  
                                                    </Grid.RowDefinitions>  
                                                    <ContentControl x:Name="Title"  
                              Margin="{ThemeResource ContentDialogTitleMargin}"  
                              Content="{TemplateBinding Title}"  
                              ContentTemplate="{TemplateBinding TitleTemplate}"  
                              FontSize="20"  
                              FontFamily="XamlAutoFontFamily"  
                              FontWeight="Normal"  
                              Foreground="{TemplateBinding Foreground}"  
                              HorizontalAlignment="Left"  
                              VerticalAlignment="Top"  
                              IsTabStop="False">  
                                                        <ContentControl.Template>  
                                                            <ControlTemplate TargetType="ContentControl">  
                                                                <ContentPresenter Content="{TemplateBinding Content}"  
                                    MaxLines="2"  
                                    TextWrapping="Wrap"  
                                    ContentTemplate="{TemplateBinding ContentTemplate}"  
                                    Margin="{TemplateBinding Padding}"  
                                    ContentTransitions="{TemplateBinding ContentTransitions}"  
                                    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"  
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />  
                                                            </ControlTemplate>  
                                                        </ContentControl.Template>  
                                                    </ContentControl>  
                                                    <ContentPresenter x:Name="Content"  
                              ContentTemplate="{TemplateBinding ContentTemplate}"  
                              Content="{TemplateBinding Content}"  
                              FontSize="{ThemeResource ControlContentThemeFontSize}"  
                              FontFamily="{ThemeResource ContentControlThemeFontFamily}"  
                              Margin="{ThemeResource ContentDialogContentMargin}"  
                              Foreground="{TemplateBinding Foreground}"  
                              Grid.Row="1"  
                              TextWrapping="Wrap" />  
                                                </Grid>  
                                            </ScrollViewer>  
                                            <Grid x:Name="CommandSpace"  
                          Grid.Row="1"  
                          HorizontalAlignment="Stretch"  
                          VerticalAlignment="Bottom"  
                          XYFocusKeyboardNavigation="Enabled"  
                          Margin="{ThemeResource ContentDialogCommandSpaceMargin}">  
                                                <Grid.ColumnDefinitions>  
                                                    <ColumnDefinition />  
                                                    <ColumnDefinition Width="0.5*" />  
                                                    <ColumnDefinition Width="0.5*" />  
                                                    <ColumnDefinition />  
                                                </Grid.ColumnDefinitions>  
                                                <Button x:Name="PrimaryButton"  
                            Content="{TemplateBinding PrimaryButtonText}"  
                            IsEnabled="{TemplateBinding IsPrimaryButtonEnabled}"  
                            Style="{TemplateBinding PrimaryButtonStyle}"  
                            ElementSoundMode="FocusOnly"  
                            HorizontalAlignment="Stretch"  
                            VerticalAlignment="Stretch"  
                            Margin="0,0,2,0"  
                            Grid.Column="0" Command="{TemplateBinding PrimaryButtonCommand}"/>  
                                                <Button x:Name="SecondaryButton"  
                            Content="{TemplateBinding SecondaryButtonText}"  
                            IsEnabled="{TemplateBinding IsSecondaryButtonEnabled}"  
                            Style="{TemplateBinding SecondaryButtonStyle}"  
                            ElementSoundMode="FocusOnly"  
                            HorizontalAlignment="Stretch"  
                            VerticalAlignment="Stretch"  
                            Margin="2,0,2,0"  
                            Grid.Column="1"  
                            Grid.ColumnSpan="2" />  
                                                <Button x:Name="CloseButton"  
                            Content="{TemplateBinding CloseButtonText}"  
                            Style="{TemplateBinding CloseButtonStyle}"  
                            ElementSoundMode="FocusOnly"  
                            HorizontalAlignment="Stretch"  
                            VerticalAlignment="Stretch"  
                            Margin="2,0,0,0"  
                            Grid.Column="3" />  
                                            </Grid>  
                                        </Grid>  
                                    </Border>  
                                </Grid>  
                            </Border>  
                        </ControlTemplate>  
                    </Setter.Value>  
                </Setter>  
            </Style>  
        </Page.Resources>  
    
     
    

    .cs:

    ContentDialog dialog = new ContentDialog  
    {  
        Title = "Some content dialog",  
        PrimaryButtonText = "Primary button",  
        PrimaryButtonCommand = new DoNothingCommand(canExecute: false)  
    };  
    dialog.Style = (Style)this.Resources["MyStyle"];  
    await dialog.ShowAsync();  
    
    1 person found this answer helpful.