wpf - проверка - как показывать всплывающие подсказки и отключать кнопку «Выполнить» - PullRequest
4 голосов
/ 01 января 2011

Привет! Мне нужно проверить некоторые текстовые поля в моем приложении.Я решил использовать правило проверки «DataErrorValidationRule».Вот почему в моем классе я реализовал интерфейс IDataErrorInfo и написал подходящие функции.В своем коде xaml я добавил привязки и правила проверки к текстовым полям

 <TextBox x:Name="txtName" Grid.Column="3" Grid.Row="1"  TextAlignment="Center" >
                        <TextBox.Text>
                            <Binding Path="Name" >
                                <Binding.ValidationRules>
                                    <DataErrorValidationRule></DataErrorValidationRule>
                                </Binding.ValidationRules>
                            </Binding>
                        </TextBox.Text>
                    </TextBox>

Проверка этого текстового поля в порядке - я имею в виду, что красная рамка появляется в текстовом поле, если данные неверны.Однако, что мне нужно сделать, это показать всплывающую подсказку в этом текстовом поле, но что более важно, я должен отключить кнопку «Выполнить», если какие-либо текстовые поля содержат неверные данные.Каков наилучший способ сделать? ??

РЕДАКТИРОВАТЬ Первая проблема была решена, но у меня есть другая.Мне нужно использовать MultiBindings для проверки моей кнопки.Итак, я сделал вот так

 <Button x:Name="btnArrange"  Grid.Column="0"  Content="Rozmieść" Click="btnArrange_Click" >
                <Button.Style>
                    <Style TargetType="Button">
                        <Style.Triggers>
                            <DataTrigger Value="False">
                                <DataTrigger.Binding>
                                    <MultiBinding Converter="{StaticResource BindingConverter}">
                                        <Binding ElementName="txtName" Path="Validation.HasError" />
                                        <Binding ElementName="txtSurname" Path="Validation.HasError"/>
                                        <Binding ElementName="txtAddress" Path="Validation.HasError"/>

                                    </MultiBinding>
                                </DataTrigger.Binding>
                                <Setter Property="IsEnabled" Value="False"/>

                            </DataTrigger>
                        </Style.Triggers>
                    </Style>        
                </Button.Style>

        </Button>

Мой конвертер выглядит так

 public  class Converters : IMultiValueConverter
{

    #region IMultiValueConverter Members

    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if(values !=null && values.Length > 0)
        {


            if (values.Cast<type>().Count(val => val) > 0)
                return false;
            return true;
        }
        return false;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }

    #endregion
}

Однако в этом конвертере я получаю invalidCastException.Каков правильный состав в этом случае?Я думаю, что HasError является типом bool, поэтому я должен приводить к типу bool.

Ответы [ 3 ]

16 голосов
/ 01 января 2011

Чтобы отобразить сообщение об ошибке во всплывающей подсказке, вставьте его в приложение. Ресурсы:

<Style x:Key="textBoxInError" TargetType="{x:Type TextBox}">
  <Style.Triggers>
    <Trigger Property="Validation.HasError" Value="true">
      <Setter Property="ToolTip"
        Value="{Binding RelativeSource={x:Static RelativeSource.Self},
                        Path=(Validation.Errors)[0].ErrorContent}"/>
    </Trigger>
  </Style.Triggers>
</Style>

(пример из http://msdn.microsoft.com/en-us/library/system.windows.controls.validation.errortemplate.aspx)

Чтобы включить / отключить кнопку, вы можете использовать что-то вроде

<Button x:Name="btnOK" Content="OK" IsDefault="True" Click="btnOK_Click">
  <Button.Style>
    <Style TargetType="{x:Type Button}">
      <Setter Property="IsEnabled" Value="false" />
      <Style.Triggers>
        <MultiDataTrigger>
          <MultiDataTrigger.Conditions>
            <Condition Binding="{Binding ElementName=txt1, Path=(Validation.HasError)}" Value="false" />
            <Condition Binding="{Binding ElementName=txt2, Path=(Validation.HasError)}" Value="false" />
          </MultiDataTrigger.Conditions>
          <Setter Property="IsEnabled" Value="true" />
        </MultiDataTrigger>
      </Style.Triggers>
    </Style>
  </Button.Style>
</Button>

или вы можете реализовать ICommand и использовать привязку команд.

EDIT

Вот полностью рабочий пример. Он отображает окно с двумя текстовыми полями. Кнопка активна тогда и только тогда, когда оба текстовых поля не пустые. Создайте проект с именем ValidationDemo и поместите в него следующие файлы:

MainWindow.xaml:

<Window x:Class="ValidationDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="146" Width="223">
  <Window.Resources>
    <Style TargetType="{x:Type TextBox}">
      <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="true">
          <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
        </Trigger>
      </Style.Triggers>
    </Style>
  </Window.Resources>
  <Grid>
    <Label Content="A" Height="28" HorizontalAlignment="Left" Margin="46,7,0,0" Name="label1" VerticalAlignment="Top" />
    <TextBox Name="txtA" Text="{Binding Path=TextA, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Height="23" HorizontalAlignment="Left" Margin="69,12,0,0" VerticalAlignment="Top" Width="120" />
    <Label Content="B" Height="28" HorizontalAlignment="Left" Margin="46,39,0,0" Name="label2" VerticalAlignment="Top" />
    <TextBox Name="txtB" Text="{Binding Path=TextB, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" Height="23" HorizontalAlignment="Left" Margin="69,41,0,0" VerticalAlignment="Top" Width="120" />
    <Button Name="btnOk" Content="OK" Height="23" HorizontalAlignment="Left" Margin="114,70,0,0" VerticalAlignment="Top" Width="75" Click="btnOk_Click">
      <Button.Style>
        <Style TargetType="{x:Type Button}">
          <Setter Property="IsEnabled" Value="false" />
          <Style.Triggers>
            <MultiDataTrigger>
              <MultiDataTrigger.Conditions>
                <Condition Binding="{Binding ElementName=txtA, Path=(Validation.HasError)}" Value="false" />
                <Condition Binding="{Binding ElementName=txtB, Path=(Validation.HasError)}" Value="false" />
              </MultiDataTrigger.Conditions>
              <Setter Property="IsEnabled" Value="true" />
            </MultiDataTrigger>
          </Style.Triggers>
        </Style>
      </Button.Style>
    </Button>
  </Grid>
</Window>

MainWindow.xaml.cs:

using System.Windows;

namespace ValidationDemo
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {

    private Model model = new Model();

    public MainWindow()
    {
      InitializeComponent();
      this.DataContext = this.model;
    }

    private void btnOk_Click(object sender, RoutedEventArgs e)
    {
      Application.Current.Shutdown();
    }
  }
}

Model.cs:

using System;
using System.ComponentModel;

namespace ValidationDemo
{
  public class Model : INotifyPropertyChanged, IDataErrorInfo
  {
    public event PropertyChangedEventHandler PropertyChanged;

    private string textA = string.Empty;
    public string TextA
    {
      get
      {
        return this.textA;
      }
      set
      {
        if (this.textA != value)
        {
          this.textA = value;
          this.OnPropertyChanged("TextA");
        }
      }
    }

    private string textB = string.Empty;
    public string TextB
    {
      get
      {
        return this.textB;
      }
      set
      {
        if (this.textB != value)
        {
          this.textB = value;
          this.OnPropertyChanged("TextB");
        }
      }
    }

    public string Error
    {
      get { throw new NotImplementedException(); }
    }

    public string this[string columnName]
    {
      get
      {
        string result = string.Empty;
        switch (columnName)
        {
          case "TextA":
            if (string.IsNullOrEmpty(this.textA))
            {
              result = "'A' must not be empty";
            }
            break;
          case "TextB":
            if (string.IsNullOrEmpty(this.textA))
            {
              result = "'B' must not be empty";
            }
            break;
        }
        return result;
      }
    }

    protected virtual void OnPropertyChanged(string propertyName)
    {
      if (this.PropertyChanged != null)
      {
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
      }
    }

  }

}
5 голосов
/ 01 января 2011
<Window.Resources>
    <Style x:Key="ElementInError" TargetType="{x:Type FrameworkElement}">
        <Style.Triggers>
            <Trigger Property="Validation.HasError" Value="True">
                <Setter Property="ToolTip"
                    Value="{Binding (Validation.Errors)[0].ErrorContent, RelativeSource={x:Static RelativeSource.Self}}"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<!-- ... -->
<TextBox x:Name="txtName" Style="{StaticResource ElementInError}">
    <!-- ... -->        
</TextBox>
<!-- ... --> 
        <Button x:Name="OkButton" Content="Ok" Margin="5" Click="OkButton_Click">
            <Button.Style>
                <Style TargetType="Button">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ElementName=txtName,Path=(Validation.HasError)}" Value="True">
                            <Setter Property="IsEnabled" Value="False" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </Button.Style>
        </Button>
2 голосов
/ 01 января 2011

Если вы создаете сводку проверки, вы можете связать свойство IsEnabled вашей кнопки «Выполнить» со свойством HasErrors.

Вам потребуется использовать промежуточное свойство или конвертер, как вы хотитеIsEnabled будет true, если HasErrors ложно (и наоборот).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...