5

わかりました、MVVM ViewModels にたくさんの ICommands を入れたくなかったので、文字列 (メソッドの名前) をフィードする WPF 用の MarkupExtension を作成することにしました。メソッドを実行する ICommand が返されます。

ここにスニペットがあります:

public class MethodCall : MarkupExtension
{
    public MethodCall(string methodName)
    {
        MethodName = methodName;
        CanExecute = "Can" + methodName;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        Binding bin = new Binding { Converter = new MethodConverter(MethodName, CanExecute) };

        return bin.ProvideValue(serviceProvider);
    }
}

public class MethodConverter : IValueConverter
{
    string MethodName;
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        //Convert to ICommand
        ICommand cmd = ConvertToICommand();
        if (cmd == null)
            Debug.WriteLine(string.Format("Could not bind to method 'MyMethod' on object", MethodName));
        return cmd;
    }
}

バインディングが失敗した場合(たとえば、タイプミスなど)を除いて、うまく機能します。

xaml でこれを行うと {Binding MyPropertyName}、バインディングが失敗するたびに出力ウィンドウに表示されます。そして、それはあなたにpropertyName、タイプ名などを教えてくれます.

MethodConverter クラスは、失敗したメソッドの名前を教えてくれますが、ソース オブジェクトの種類を教えてくれません。値が null になるためです。

ソースオブジェクトタイプを格納する方法がわからないので、次のクラスについて

public class MyClass
{
    public void MyMethod()
    {
    }
}

および次の xaml:

<Button Command={d:MethodCall MyMethod}>My Method</Button>

現在、次のように述べています。

"Could not bind to method 'MyMethod' on object

しかし、私はそれを言いたい:

"Could not bind to method 'MyMethod' on object MyClass

何か案は?

4

2 に答える 2

2

うーん、まぁ、回り道が思いつきます。もっと簡単できれいなものがあるかもしれませんが、これを試してください:

  1. IProvideValueTarget経由で実装を取得しIServiceProviderます。
  2. ターゲット情報を使用しBindingExpressionて、バインドされたプロパティの a を解決します。
  3. DataItemのプロパティを使用してBindingExpression、ソース オブジェクトを取得します。

何かのようなもの:

var provideValueTarget = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
var bindingExpression = BindingOperations.GetBindingExpression(provideValueTarget.TargetObject, (DependencyProperty)provideValueTarget.TargetProperty);
var source = bindingExpression.DataItem;

ひどいですが、うまくいくはずです。これを行うサービスがあるかもしれませんが、MSDN をざっと見ても見つかりませんでした。

于 2010-03-29T18:12:15.580 に答える
0

CanExecuteChangedこれはバインディングではありません。コマンド オブジェクトにはイベントがあるため、コマンドの場合はバインディングは必要ありません。

public override object ProvideValue(IServiceProvider serviceProvider)  
{    
    ICommand cmd = ConvertToICommand();
    return cmd;
}

ConverTOICommand常に何かを返すようにしてください。null コマンドか何かについて考える時間です。

于 2011-04-22T18:56:50.790 に答える