11

MVVM Light V3 alpha3を使用してWPF4アプリ(VS2010 RCを使用)を作成していますが、ここで奇妙な動作が発生しています...

を開くコマンドがありWindow、そのウィンドウがViewModelなどを作成します-そこには何も奇妙なことはありません。

その中でWindow私はいくつかRelayCommandの例を持っています:

CategoryBeenSelected = new RelayCommand(() => OnCategoryUpdate = true);

再び奇妙なことは何もありません-それは私が期待したように動作します。

問題は、汎用のRelayCommandでCanExecuteメソッド/ラムダ式を使用できないことです。

これは機能します:

DeleteCategoryCommand = new RelayCommand<int>(DeleteCategory);

しかし、これはしません:

DeleteCategoryCommand = new RelayCommand<int>(DeleteCategory, CanDeleteCategory);

ウィンドウが表示されません。つまり、ウィンドウを開くボタンをクリックすると、アプリがブロックされ、数秒後に、ウィンドウのメソッドが(オブジェクトのインスタンスに設定されていないオブジェクト参照)InitializeComponentをスローします。NullReferenceException

つまり、CanExecuteメソッドをに配置するRelayCommand<T>と、そのViewModel(を含む)Window所有するRelayCommand<T>はインスタンス化できません。を削除するCanExecuteと、がWindow表示されます。

ここで問題はどこにありますか?よくわかりません。

ありがとうございました。

編集:要求に応じて、ここにスタックトレースがあります:

タイプ'System.NullReferenceException'の最初のチャンスの例外がPresentationFramework.dllで発生しました
   GalaSoft.MvvmLight.Command.RelayCommand`1.CanExecute(Objectパラメーター)で
   System.Windows.Controls.Primitives.ButtonBase.UpdateCanExecute()で
   System.Windows.Controls.Primitives.ButtonBase.OnCommandChanged(DependencyObject d、DependencyPropertyChangedEventArgs e)で
   System.Windows.DependencyObject.OnPropertyChanged(DependencyPropertyChangedEventArgs e)で
   System.Windows.FrameworkElement.OnPropertyChanged(DependencyPropertyChangedEventArgs e)で
   System.Windows.DependencyObject.NotifyPropertyChange(DependencyPropertyChangedEventArgs args)で
   System.Windows.DependencyObject.UpdateEffectiveValue(EntryIndex entryIndex、DependencyProperty dp、PropertyMetadataメタデータ、EffectiveValueEntry oldEntry、EffectiveValueEntry&newEntry、ブールcoerceWithDeferredReference、ブールcoerceWithCurrentValue、OperationType operationType)
   System.Windows.DependencyObject.SetValueCommon(DependencyProperty dp、Object value、PropertyMetadataメタデータ、ブールcoerceWithDeferredReference、ブールcoerceWithCurrentValue、OperationType operationType、ブールisInternal)で
   System.Windows.DependencyObject.SetValue(DependencyProperty dp、Object value)で
   MS.Internal.Xaml.Runtime.ClrObjectRuntime.SetValue(Object inst、XamlMember property、Object value)で
   MS.Internal.Xaml.Runtime.PartialTrustTolerantRuntime.SetValue(Object obj、XamlMember property、Object value)で
   System.Xaml.XamlObjectWriter.Logic_ApplyPropertyValue(ObjectWriterContext ctx、XamlMember prop、Object value、Boolean onParent)で
   System.Xaml.XamlObjectWriter.Logic_DoAssignmentToParentProperty(ObjectWriterContext ctx)で
   System.Xaml.XamlObjectWriter.WriteEndObject()で
   System.Windows.Markup.WpfXamlLoader.TransformNodes(XamlReader xamlReader、XamlObjectWriter xamlWriter、Boolean onlyLoadOneNode、Boolean skipJournaledProperties、Boolean shouldPassLineNumberInfo、IXamlLineInfo xamlLineInfo、IXamlLineInfoConsumer xamlLineInfoConsumer、XamlContextStack
   System.Windows.Markup.WpfXamlLoader.Load(XamlReader xamlReader、IXamlObjectWriterFactory writerFactory、Boolean skipJournaledProperties、Object rootObject、XamlObjectWriterSettings settings、Uri baseUri)で
   System.Windows.Markup.WpfXamlLoader.LoadBaml(XamlReader xamlReader、Boolean skipJournaledProperties、Object rootObject、XamlAccessLevel accessLevel、Uri baseUri)で
   System.Windows.Markup.XamlReader.LoadBaml(ストリームストリーム、ParserContext parserContext、オブジェクトの親、ブール値closeStream)で
   System.Windows.Application.LoadComponent(Object component、Uri resourceLocator)で
   c:\ Users \ Jesus \ Documents \ Visual Studio 2010 \ Projects \ ApuntaNotas \ ApuntaNotas \ Views \ CategoryEditorView.xaml:line 1のApuntaNotas.Views.CategoryEditorView.InitializeComponent()
   C:\ Users \ Jesus \ Documents \ Visual Studio 2010 \ Projects \ ApuntaNotas \ ApuntaNotas \ Views \ CategoryEditorView.xaml.cs:line 18のApuntaNotas.Views.CategoryEditorView..ctor()
タイプ'System.NullReferenceException'の最初のチャンスの例外がPresentationFramework.dllで発生しました
4

4 に答える 4

7

RelayCommandは、パラメータの値を汎用Tにキャストするようです。

ただし、例外が示すように、構造体にnullをキャストすることはできません。

null許容構造体を使用してRelayCommandを初期化すると、期待どおりに機能します。

RelayCommand<int?> or RelayCommand<Nullable<int>>

HTH

于 2010-02-23T16:34:44.140 に答える
2

Arcturusは問題が何であるかを特定するのに正しかったが、null許容プリミティブを使用するソリューションは気に入らなかった。個人的には、null許容プリミティブを使用する十分な理由がない限り、null許容プリミティブは好きではありません。

代わりに、RelayCommandの実装を次のように変更しました。

    bool ICommand.CanExecute(object parameter)
    {
        if (parameter == null && typeof(T).IsValueType)
        {
            return CanExecute(default(T));
        }
        return CanExecute((T)parameter);
    }

コマンドが実際に引数を期待している場合に失敗するのは不合理ではないと思うので、(少なくとも今のところは)一般的なExecuteメソッドに対してこれと同じ変更を加えませんでした。

CanExecuteの問題は、特定のバインディングを評価する前に、WPFシステムがCanExecuteを呼び出すことがあることです。例えば:

        <Button Content="Fit To Width" Command="{Binding Path=FitToWidthCommand}" CommandParameter="{Binding ElementName=imageScrollViewer, Path=ActualWidth}" />
        <Button Content="Fit To Height" Command="{Binding Path=FitToHeightCommand}" CommandParameter="{Binding ElementName=imageScrollViewer, Path=ActualHeight}" />

上記のXAMLでは、コマンドパラメーターがコントロールの実際の幅にバインドされていることがわかります。ただし、WPFは、「imageScrollViewer」コントロールが必然的にレイアウト/レンダリングされる前に、ボタンのコマンドでCanExecuteを呼び出します。したがって、実際の幅/高さはありません。ユーザーがボタンをクリックして実行が呼び出されるまでに、もちろん、値がコマンドに送信されるようにコントロールが配置されます。そうでない場合-私は失敗が予想されることだと思います-しかし、ユーザーが実際にボタンをクリックしたときだけです。

もちろん、CanExecuteとExecuteの異なる動作は好きではありませんが、今のところ、フレームワークによって提示される制限の範囲内に収まっているようです。これが私に悲しみをもたらすシナリオを見つけるかもしれませんが、私はこれまでのところその変化が好きでした。

于 2011-02-23T18:41:41.680 に答える
1

パーティーに非常に遅れましたが、私はこれに頭を悩ませていました。問題は、間違った名前空間をインポートしたことでした。

私はインポートすべきだった:

using GalaSoft.MvvmLight.CommandWpf;

しかし、私はインポートしました:

using GalaSoft.MvvmLight.Command;

これが誰かに役立つことを願っています!

于 2019-10-08T13:38:42.720 に答える
0

たぶん、現時点では、パラメータはnull

于 2010-02-22T00:21:49.163 に答える