question

aloha1 avatar image
0 Votes"
aloha1 asked ·

ContentDialog ignoring CanExecute

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

windows-uwpwindows-uwp-xaml
· 6
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Does @FayWang-MSFT 's replay make sense? Have you solved the issue?

0 Votes 0 · ·

Hi, is there any update? Do you have other questions?

0 Votes 0 · ·

Hi, is there any update?

0 Votes 0 · ·

I haven't heard from you for a while. Have you solved your issue?

0 Votes 0 · ·

Hi FayWang, thanks for the answer. I haven't tried your answer yet, but I will. Got sidetracked on another project at work. I have a feeling your solution will work. I will get back to you when I try your solution out. Thank you!

0 Votes 0 · ·

OK, got it. If you have any question, please feel free to contact us.

0 Votes 0 · ·

1 Answer

FayWang-MSFT avatar image
1 Vote"
FayWang-MSFT answered ·

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();

· 5 · Share
10 |1000 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

This solution worked great. Thank you, FayWang!

0 Votes 0 · ·

I would like to accept the answer you gave, but I can't remember the e-mail associated with aloha1. Can you accept the answer for me? Thank you.

0 Votes 0 · ·

One issue that I ran into though is that the primarycommand is called twice for some reason. I have not called the command to raise canexecutechanged anywhere else.

0 Votes 0 · ·

In which secnario the primarycommand will be triggered twice even if you didn't click the button? When I tested it, it worked well.

0 Votes 0 · ·

Sorry, I meant when I click the button, the primary command gets triggered twice.

0 Votes 0 · ·