对话框中的“确定”按钮未启用

时间:2016-03-05 21:52:35

标签: c# wpf validation mvvm mvvm-light

我正在使用MVVM Light构建WPF应用程序。在其中我有一个对话框。 XAML:

<Window x:Class="ParserEditor.NewParserDialog"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ParserEditor"
        xmlns:ignore="http://www.galasoft.ch/ignore"
        mc:Ignorable="d ignore"
        DataContext="{Binding NewParser, Source={StaticResource Locator}}"
        Title="New Parser..."
        SizeToContent="Height"
        Width="300">

    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Skins/MainSkin.xaml" />
            </ResourceDictionary.MergedDictionaries>

            <BitmapImage x:Key="ErrorImage" UriSource="Resources/Error.png" />

            <local:BooleanToVisibilityConverter x:Key="BoolToVisiblity" True="Visible" False="Collapsed" />

            <ControlTemplate x:Key="InputErrorTemplate">
                <DockPanel LastChildFill="True">
                    <Image DockPanel.Dock="Right"
                           Height="16"
                           Margin="5"
                           Source="{StaticResource ErrorImage}"
                           ToolTip="Contains invalid data"
                           VerticalAlignment="Center"
                           Width="16" />
                    <Border BorderBrush="Red"
                            BorderThickness="2">
                        <AdornedElementPlaceholder />
                    </Border>
                </DockPanel>
            </ControlTemplate>

            <Style TargetType="ComboBox">
                <Setter Property="Margin" Value="5,4,26,4" />
                <Setter Property="Validation.ErrorTemplate" Value="{StaticResource InputErrorTemplate}" />
                <Style.Triggers>
                    <Trigger Property="Validation.HasError" Value="True">
                        <Setter Property="ToolTip">
                            <Setter.Value>
                                <Binding Path="(Validation.Errors).CurrentItem.ErrorContent" RelativeSource="{x:Static RelativeSource.Self}" />
                            </Setter.Value>
                        </Setter>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ResourceDictionary>
    </Window.Resources>

    <Grid Name="LayoutRoot">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="10" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="10" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <TextBlock Name="PromptLabel"
                   Grid.Column="0"
                   Grid.ColumnSpan="2"
                   Grid.Row="0"
                   Text="{Binding Path=Prompt, Mode=TwoWay}"
                   Visibility="{Binding Path=HasPrompt, Converter={StaticResource BoolToVisiblity}}"/>

        <TextBlock Name="ParserTypeLabel"
                   Grid.Column="0"
                   Grid.Row="2"
                   Text="Parser Type:" />

        <ComboBox Name="ParserTypePicker"
                  Grid.Column="1"
                  Grid.Row="2"
                  ItemsSource="{Binding Path=ParserTypes}"
                  SelectedItem="{Binding Path=ParserType, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" />

        <Grid Name="ButtonGrid" 
              Grid.Column="0"
              Grid.ColumnSpan="2"
              Grid.Row="4">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>

            <Button Name="OkButton"
                    Command="{Binding CloseCommand, ValidatesOnDataErrors=True}"
                    Grid.Column="0"
                    Content="OK"
                    IsDefault="True" />
            <Button Name="CancelButton"
                    Grid.Column="1"
                    Content="Cancel"
                    IsCancel="True" />
        </Grid>
    </Grid>
</Window>

视图模型对象:

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using ParserEditor.Model;

namespace ParserEditor.ViewModel {

    public class NewParserViewModel : ViewModelBase, IDataErrorInfo {

        private readonly IDataService _dataService;

        public string ParserType {
            get { return _ParserType; }
            set { Set( ref _ParserType, value ); }
        }
        private string _ParserType;

        public ObservableCollection<string> ParserTypes { get; private set; }

        public bool HasPrompt {
            get { return !string.IsNullOrWhiteSpace( Prompt ); }
        }

        public string Prompt {
            get { return _Prompt; }
            set {
                Set( ref _Prompt, value );
                RaisePropertyChanged( nameof( HasPrompt ) );
            }
        }
        private string _Prompt;

        #region CloseCommand

        public RelayCommand CloseCommand { get; private set; }

        private bool CanCloseDialog() {
            return ParserType == DataService.AWK_FORMAT || 
                   ParserType == DataService.CSHARP_FORMAT || 
                   ParserType == DataService.REGEX_FORMAT;
        }

        private void CloseDialog() {
            Messenger.Default.Send( new CloseWindowMessage() );
        }

        #endregion

        #region IDataErrorInfo Implementation

        public string Error {
            get { return this[ "ParserType" ]; }
        }

        public string this[ string columnName ] {
            get {
                switch ( columnName ) {
                    case "ParserType":
                        return string.IsNullOrWhiteSpace( ParserType ) ? "You must choose a Parser Type" : null;

                    default:
                        return null;
                }
            }
        }

        #endregion

        public NewParserViewModel( IDataService dataService ) {
            _dataService = dataService;

            CloseCommand = new RelayCommand( CloseDialog, CanCloseDialog );

            ParserTypes = new ObservableCollection<string>();

            ParserTypes.Add( DataService.AWK_FORMAT );
            ParserTypes.Add( DataService.CSHARP_FORMAT );
            ParserTypes.Add( DataService.REGEX_FORMAT );
        }
    }
}

我在CanCloseDialog method中放置了一个断点,当第一次显示对话框时,它只被击中一次。如果在显示对话框后在ComboBox中选择了一个选项,则“确定”按钮不会启用。

我错过了什么?

2 个答案:

答案 0 :(得分:1)

我做了更多的搜索&amp;我终于找到了答案here。事实证明我必须改变

using GalaSoft.MvvmLight.Command;

声明

GalaSoft.MvvmLight.CommandWpf;

这样做,一切正常。

答案 1 :(得分:0)

尝试委托Func,而不是调用CanCloseDialog。 不知怎的,RelayCommand失去指向没有委托的方法的指针。 在RelayCommand实现的CanExecute方法中调用委托。

类似的东西:

incAnonymous