6

私のビューモデルとモデルには、署名付きのメソッドがありbool IsPropertyReadOnly(string propertyName)ます。このメソッドは、現在ログインしているユーザーがプロパティ値を編集できるかどうかを決定します。少数のユーザーはプロパティ値を編集でき、他のほとんどのユーザーは読み取り専用アクセス権を持ちます。

モデルの各プロパティの読み取り専用ステータスを返すプロパティを作成する代わりに、の結果をプロパティにバインドしたいと考えてIsPropertyReadOnyTextBox.IsReadOnlyます。

これが私が構文を想像する方法です:

<TextBox Text="{Binding Address, Mode=TwoWay}" 
         IsReadOnly="{Binding MethodName=IsPropertyReadOnly MethodParameter=Address}"
/>

にはDataContextビューモデルが含まれているため、基本的にIsReadOnly呼び出しの結果にバインドする必要があります((Class)this.DataContext).IsPropertyReadOnly("Address")

の使用については多くのドキュメントがありObjectDataProviderますが、オブジェクト データ プロバイダーは新しいオブジェクト インスタンスを作成しますが、これは私が望むものではありません。さらに、既存のインスタンスを使用するには、コード ビハインドで割り当てを行う必要があります。繰り返しますが、私がやりたいことではありません。

私の調査によると、私のニーズを継承するBindingMarkupExtension、より適したソリューションのようです。

どんな助けでも大歓迎です。

4

3 に答える 3

4

さらに、既存のインスタンスを使用するには、コードビハインドで割り当てを行う必要があります。繰り返しますが、私がやりたいことではありません。

それは真実ではありません、しかしあなたの選択は制限されます。


インデクサーはどうですか?

private readonly Dictionary<string, bool> _PropertyReadOnlyDictionary = new Dictionary<string, bool>();
public Dictionary<string, bool> PropertyReadOnlyDictionary { get { return _PropertyReadOnlyDictionary; } }
<TextBox Text="{Binding Address, Mode=TwoWay}"
        IsReadOnly="{Binding PropertyReadOnlyDictionary[Address]}" />

もちろん、辞書を使用したくない場合は、インデクサーを介したアクセスを許可する新しいクラスでメソッドをラップすることもできます。

private readonly PropertyIsReadOnlyResolver _PropertyIsReadOnlyResolver = new PropertyIsReadOnlyResolver();
public PropertyIsReadOnlyResolver PropertyIsReadOnlyResolver { get { return _PropertyIsReadOnlyResolver; } }
public class PropertyIsReadOnlyResolver
{
    public bool this[string propertyName]
    {
        get
        {
            return IsPropertyReadOnly(propertyName);
        }
    }

    public bool IsPropertyReadOnly(string propertyName)
    {
        //...
    }
}
<TextBox Text="{Binding Address, Mode=TwoWay}"
        IsReadOnly="{Binding PropertyIsReadOnlyResolver[Address]}" />
于 2012-02-06T14:56:13.377 に答える
4

コンバーターの使用をお勧めします。これが例です。シンプルな ViewModel クラスがあるとします。

class ViewModel
{
    public string Read
    { get; set; }

    public string ReadWrite
    { get; set; }

    public bool IsPropertyReadOnly(string propertyName)
    {
        return propertyName != "ReadWrite";
    }
}

問題を解決するには、次のようなコンバーターを作成する必要があります。

public class Converter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var vm = value as ViewModel;
        var functionName = (string)parameter;

        var result = vm.IsPropertyReadOnly(functionName);
        return result;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException("This method should never be called");
    }
}

それだけです。次のように、XAML でこのコンバーターを使用できるようになりました。

<Window.Resources>
    <temp:Converter x:Key="ReadOnlyMethodConverter"/>
</Window.Resources>
<StackPanel>
    <TextBox Text="{Binding Read, Mode=TwoWay}" 
             IsReadOnly="{Binding Path=.,
        Converter={StaticResource ReadOnlyMethodConverter}, ConverterParameter=Read}"
    />
    <TextBox Text="{Binding ReadWrite, Mode=TwoWay}" 
             IsReadOnly="{Binding Path=.,
        Converter={StaticResource ReadOnlyMethodConverter}, ConverterParameter=ReadWrite}"
    />
</StackPanel>

コード ビハインドでは、ViewModel を作成して DataContext として設定するだけです。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel();
    }
}
于 2012-02-06T12:19:42.647 に答える
0

ObjectDataProviderを使用してメソッドを実行し、添付プロパティをプロバイダーの戻り値にバインドすることで、これを実行できるはずです。

まず、プロバイダーをリソースとして構成する必要があります。

<Window.Resources>
  <ObjectDataProvider x:Key="readOnlyProvider" ...>
    <ObjectDataProvider.MethodParameters>
      ...
    </ObjectDataProvider.MethodParameters>
  </ObjectDataProvider>
</Window.Resources>

次に、プロバイダーを添付プロパティ バインディングのソースとして使用します。

<TextBox Text="{Binding PoolNum, Mode=OneWay}" Windows:AttachedProperties.IsReadOnlyOn="{Binding Source={StaticResource readOnlyProvider}}" />

このプロセスのトリッキーな部分は、 に値を「渡す」ことObjectDataProviders.MethodParametersです。これは XAML で行うことができ、その方法を示すリソースがいくつかあります。ここから始めましょう: http://weblogs.asp.net/psheriff/archive/2010/02/23/bind-objectdataprovider-method-parameters-in-wpf.aspx

アップデート

あなたのコメントによると、新しいオブジェクトを作成せずObjectDataProviderにビューでメソッドを実行できる2つの方法があります。DataContext

まず、ビュー モデル メソッドを静的にし、次のObjectTypeプロパティを使用します。

<ObjectDataProvider x:Key="readOnlyProvider"
  ObjectType="{x:local MyDataContext}"
  MethodName="IsPropertyReadOnly">
  ...
</ObjectDataProvider>

または、ビューの読み込み時にObjectInstanceプロバイダーのをビューに設定します。DataContext

public class MyWindow : Window
{
  public MyWindow()
  {
    InitializeComponent();

    var readOnlyProvider = this.Resources["readOnlyProvider"] as ObjectDataProvider;
    readOnlyProvider.ObjectInstance = this.DataContext;
  }
}

XAML でメソッドにバインドする方法はなく、私が知っている唯一の回避策はObjectDataProvider.

于 2012-02-04T00:12:50.413 に答える