Wpf - Default Button not Working as Expected

14,216

Solution 1

The IsDefault property only means that this button is "clicked" when the ENTER key is pressed. It doesn't close the dialog, and doesn't set the DialogResult, you have to do it manually in code-behind :

private void BtnOK_Click(object sender, RoutedEventArgs e)
{
    this.DialogResult = true;
}

(setting DialogResult also closes the window)

Solution 2

To make things nicer, you could use an attached property like this one:

<Button Content="OK" IsDefault="True" local:DialogBehaviours.OkButton="true" 
Height="23" HorizontalAlignment="Left" Width="75" />

the attached property can be defined as such:

public class DialogBehaviours
{

    /*
        OkButton property.

        An attached property for defining the Accept (OK) button on a dialog.
        This property can be set on any button, if it is set to true, when enter is pressed, or
        the button is clicked, the dialog will be closed, and the dialog result will be set to
        true.
    */
    public static bool GetOkButton(DependencyObject obj)
    {return (bool)obj.GetValue(OkButtonProperty);       }

    public static void SetOkButton(DependencyObject obj, bool value)
    {obj.SetValue(OkButtonProperty, value);     }

    public static readonly DependencyProperty OkButtonProperty =
        DependencyProperty.RegisterAttached("OkButton", typeof(bool), typeof(Button), new UIPropertyMetadata(false, OnOkButtonPropertyChanged_));

    static void OnOkButtonPropertyChanged_(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        if (!(obj is Button) || !(e.NewValue is bool))
            return;

        Button button = (Button)obj;
        bool value = (bool)e.NewValue;

        if (value)
            button.Click += OnAcceptButtonClicked_;
        else
            button.Click -= OnAcceptButtonClicked_;

        button.IsDefault = value;
    }

    static void OnAcceptButtonClicked_(object sender, RoutedEventArgs e)
    {
        if (!(sender is DependencyObject))
            return;

        Window parent = FindParent<Window>((DependencyObject)sender, (c) => true);
        if (parent != null)
        {
            try { parent.DialogResult = true; }
            catch (Exception)
            {
                parent.Close();
            }
        }
    }

    public static T FindParent<T>(DependencyObject obj, Predicate<T> predicate) where T : FrameworkElement
    {
        if (obj == null || predicate == null)
            return null;

        if (obj is T)
        {
            T control = (T)obj;
            if (predicate(control))
                return control;
        }

        DependencyObject parent = VisualTreeHelper.GetParent(obj);
        return (parent == null) ? null : FindParent<T>(parent, predicate);
    }
}
Share:
14,216

Related videos on Youtube

photo_tom
Author by

photo_tom

I'm an "experienced" programmer who has made a point of never doing the same job twice. As a result, I've gotten so that I prefer projects that don't just use one technology, but a collection of related ones. Primarily a Windows programmer who loves .Net, but native c++/Qt/Boost comes in a close second. The world of programming is an interesting place that is changing at an ever faster pace. There are so many new and really wonderful ideas, frameworks, library, etc, being released every day that is is like drinking from a fire hose to keep up. But who is complaining

Updated on April 21, 2022

Comments

  • photo_tom
    photo_tom about 2 years

    I'm having a problem with the default Button in the xaml code below:

    <Window x:Class="WebSiteMon.Results.Views.GraphicSizeSelectPopUp"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:commonWPF="http://rubenhak.com/common/wpf"
            xmlns:WPF="clr-namespace:Bennedik.Validation.Integration.WPF;assembly=Bennedik.Validation.Integration.WPF"
            ResizeMode="NoResize"
            WindowStyle="ThreeDBorderWindow"
            SizeToContent="WidthAndHeight">
      <Window.Resources>
        <Style TargetType="{x:Type TextBox}">
          <Setter Property="Validation.ErrorTemplate">
            <Setter.Value>
              <ControlTemplate>
                <Border BorderBrush="Red"
                        BorderThickness="2">
                  <AdornedElementPlaceholder />
                </Border>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
          <Style.Triggers>
            <Trigger Property="Validation.HasError"
                     Value="true">
              <Setter Property="ToolTip"
                      Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}" />
            </Trigger>
          </Style.Triggers>
        </Style>
      </Window.Resources>
      <WPF:ErrorProvider x:Name="UrlDataErrorProvider"
                         RulesetName="RuleSetA">
        <Grid Background="{DynamicResource WindowBackgroundBrush}">
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="25" />
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
          </Grid.ColumnDefinitions>
          <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
          </Grid.RowDefinitions>
    
          <RadioButton Grid.ColumnSpan="2"
                       Margin="10"
                       Name="radioButton1"
                       Content="640 x 480 pixels"
                       Command="{Binding SelectSizeRb}"
                       CommandParameter="640,480" />
          <RadioButton Grid.ColumnSpan="2"
                       Margin="10"
                       Name="radioButton2"
                       Content="800 x 600 pixels"
                       Command="{Binding SelectSizeRb}"
                       CommandParameter="800,600"
                       Grid.Row="1"
                       IsChecked="True" />
          <RadioButton Grid.ColumnSpan="2"
                       Margin="10"
                       Name="radioButton3"
                       Content="1024 x 768 pixels"
                       Command="{Binding SelectSizeRb}"
                       CommandParameter="1024,768"
                       Grid.Row="2" />
          <RadioButton Grid.ColumnSpan="2"
                       Margin="10"
                       Name="radioButton4"
                       Command="{Binding SelectSizeRb}"
                       CommandParameter="0,0"
                       Grid.Row="3" />
    
          <Button Grid.Column="1"
                  Grid.ColumnSpan="1"
                  Grid.Row="5"
                  Margin="5"
                  Name="BtnOk"
                  IsDefault="True">Ok</Button>
          <Button Grid.Column="2"
                  Grid.ColumnSpan="1"
                  Grid.Row="5"
                  Margin="5"
                  Name="BtnCancel"
                  IsCancel="True">Cancel</Button>
    
        </Grid>
      </WPF:ErrorProvider>
    </Window>
    

    I call the above window using the following code:

    var p = new GraphicSizeSelectPopUp();
    var result = p.ShowDialog() ?? false;
    p.Close();
    

    I'm using this as a Popup window in my application to get some info from the user. My problem is the when I click on the OK button, nothing happens. The Cancel button works exactly as expected, meaning that control returns in the calling program from the ShowDialog method.

    As I understand WPF (still newbie), all I have to do is set the IsDefault property to true for the default button to do the same. However, this is not what I'm seeing. When I set a breakpoint on the line after the ShowDialog method, it is not hit when I press the okay button. Only when I press the Cancel button or close the window.

    Suggestions for the uninformed?

  • Ignacio Soler Garcia
    Ignacio Soler Garcia over 11 years
    Not very consistent with the IsCancel that sets the DialogResult. By the way, setting the DialogResult is enough, setting it closes the window.