2009-12-29 2 views
16

Sto avendo un problema con il default Button nel codice XAML di seguito:WPF - Pulsante di default non funziona come previsto

<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> 

io chiamo la finestra sopra utilizzando il seguente codice:

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

Sto usando questa come una finestra Popup nella mia applicazione per ottenere alcune informazioni dall'utente. Il mio problema è quando clicco sul pulsante OK, non succede nulla. Il pulsante Cancel funziona esattamente come previsto, ovvero restituisce il controllo nel programma chiamante dal metodo ShowDialog.

Come ho capito WPF (ancora newbie), tutto quello che devo fare è impostare la proprietà IsDefault su true affinché il pulsante predefinito faccia lo stesso. Tuttavia, questo non è quello che sto vedendo. Quando imposto un breakpoint sulla linea dopo il metodo ShowDialog, non viene colpito quando premo il pulsante OK. Solo quando premo il pulsante Cancel o chiudo la finestra.

Suggerimenti per i non informati?

risposta

26

La proprietà IsDefault significa solo che questo pulsante viene "cliccato" quando si preme il tasto INVIO. Non chiudere la finestra, e non imposta il DialogResult, è necessario farlo manualmente in code-behind:

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

(impostazione DialogResult chiude anche la finestra)

+8

Non molto coerente con IsCancel che imposta DialogResult. A proposito, è sufficiente impostare il DialogResult, impostandolo per chiudere la finestra. –

+0

@SoMoS, hai ragione, ovviamente. Ho rimosso la chiamata a Chiudi. –

8

Per rendere le cose più bello , è possibile utilizzare una proprietà associata come questo:

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

proprietà associata può essere definito come tale:

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