1

入力された値が既に存在する場合にエラーを返す検証ノードを作成する必要があります。名前を設定できる項目の GUI があります。名前を一意にする必要があります。

したがって、検証ごとに、次の 2 つのパラメーターが必要です。

  • すべてのアイテムのすべての名前のリスト、または名前が存在することを知らせる述語
  • 上記の検証から除外する現在のアイテム名 (名前を同じ値に変更してもエラーにはなりません)

データ コンテキストは次のようになります (説明のためのインターフェイスのみ)。

class AppMainContext
{
  public IEnumerable<string> ItemNames {get;}
  public Item SelectedItem {get;}
}

class Item 
{
  public string Name {get;}
}

WPF のフィールドは次のようになり、その親は `{SelectedItem} にバインドされます。

<DockPanel DockPanel.Dock="Top">
  <Label Content="Name: "/>
  <TextBox DockPanel.Dock="Top">
    <TextBox.Text>
      <Binding Path="Name" UpdateSourceTrigger="PropertyChanged">
        <Binding.ValidationRules>
          <vmvalidation:UniqueNameRule  />
        </Binding.ValidationRules>
      </Binding>
    </TextBox.Text>
  </TextBox>
</DockPanel>

バリデータは次のようになります。

using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Controls;

namespace MyApp.Validation
{
  public class UniqueNameRule : ValidationRule
  {
    public IEnumerable<string> ExistingNames { get; set; }

    public string MyName { get; set; }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
      if(value is string newValue)
      {
        // name changed
        if(!value.Equals(MyName))
        {
          if(ExistingNames.Contains(newValue))
          {
            return new ValidationResult(false, "Name already exists!");
          }
        }
        return new ValidationResult(true, null);
      }
      else
      {
        return new ValidationResult(false, "Invalid value type. Is this validator valid for the given field?");
      }
    }
  }
}

少なくとも現在の名前をバリデーターにバインドしようとしました。テキスト ボックスは現在のアイテム データ コンテキストに既に存在するため、正しいバインドは次のようになります。

<Binding.ValidationRules>
  <vmvalidation:UniqueNameRule MyName="{Binding Name}"  />
</Binding.ValidationRules>

これによりエラーが発生することを除いて:

メンバーMyNameが認識されていないか、アクセスできません。

すべての項目のリストは Windows データ コンテキストにあり、 からアクセスできますItemNames。次のようにアクセスできると思います。

{Binding Path=DataContext.ItemNames, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}

以下の回答を使用して正しいバインディングを試みましたが、エラーが発生しました。

タイプ の 'MyName' プロパティに 'Binding' を設定することはできませんMyProject_Validation_UniqueNameRule_9_468654。「Binding」は、DependencyObject の DependencyProperty でのみ設定できます。

バインディングはまったくサポートされていないようです。

では、検証ルールがこれらの変数の両方にアクセスできるようにするには、どうすればこれをまとめることができるでしょうか?

4

1 に答える 1