10

ビューモデル:

public class MyViewModel
{
    [Required, StringLength(50)]
    public String SomeProperty { ... }
}

XAML:

<TextBox Text="{Binding SomeProperty}" MaxLength="50" />

TextBox の MaxLength を ViewModel (別のアセンブリにあるため変更される可能性があります) と一致するように設定しないようにし、StringLength 要件に基づいて最大長を自動的に設定する方法はありますか?

4

5 に答える 5

18

Behaviorを使用して、TextBox をバインドされたプロパティの検証属性 (存在する場合) に接続しました。動作は次のようになります。

/// <summary>
/// Set the maximum length of a TextBox based on any StringLength attribute of the bound property
/// </summary>
public class RestrictStringInputBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        AssociatedObject.Loaded += (sender, args) => setMaxLength();
        base.OnAttached();
    }

    private void setMaxLength()
    {
        object context = AssociatedObject.DataContext;
        BindingExpression binding = AssociatedObject.GetBindingExpression(TextBox.TextProperty);

        if (context != null && binding != null)
        {
            PropertyInfo prop = context.GetType().GetProperty(binding.ParentBinding.Path.Path);
            if (prop != null)
            {
                var att = prop.GetCustomAttributes(typeof(StringLengthAttribute), true).FirstOrDefault() as StringLengthAttribute;
                if (att != null)
                {
                    AssociatedObject.MaxLength = att.MaximumLength;
                }
            }
        }
    }
}

ご覧のとおり、動作はテキスト ボックスのデータ コンテキストと、"Text" のバインディング式を取得するだけです。次に、リフレクションを使用して「StringLength」属性を取得します。使い方はこんな感じです。

<UserControl
    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

    <TextBox Text="{Binding SomeProperty}">
        <i:Interaction.Behaviors>
            <local:RestrictStringInputBehavior />
        </i:Interaction.Behaviors>
    </TextBox>

</UserControl>

を拡張してこの機能を追加することもできますがTextBox、ビヘイビアーはモジュラーであるため、ビヘイビアーを使用するのが好きです。

于 2013-02-07T21:47:26.493 に答える
1

自分でコードを完全に書き出すつもりはありませんが、1 つのアイデアは、独自のコードを作成してMarkupExtension、プロパティ名を取得し、StringLengthAttribute.

属性が存在する場合は、(リフレクションを使用して) ターゲットをその値にバインドしようとします。そうでない場合は、0 をターゲット値にバインドします (0 がデフォルト、つまり最大値なし)。

于 2012-01-05T19:18:05.950 に答える
0

Markup 拡張機能は間違いなく最適な方法です。モデルの DataType 依存プロパティを持つ Binding という BindingDecoratorBase のサブクラスを作成しています。MarkupExtensions は InitializeComponent() 中に作成されるため、DataContext はまだ設定されていないため、決定する方法はありません。

モデル タイプを指定すると、モデルで定義された属性へのリフレクション アクセスが可能になります。これにより、次のことが可能になります。

  • TextBoxes の MaxLength を設定します。
  • TextBlocks の StringFormat を設定します。
  • メンバーのデータ型に応じて、既定のコンバーターを設定します。
  • 必要な検証を追加します。バインディングの ValidationRules を使用するか、ValidatesOnDataErrors を設定します。

マークアップは次のようになります: Text="{PO:Binding DataType=model:modAccount, Path=SubAccount}"

Formatting、MaxLength、および Conversion が 1 つのパッケージにまとめられ、モデル クラスが変更されても何も変更する必要はありません。

于 2015-05-09T23:13:47.657 に答える
0

これを行う 1 つの方法は、同じビューモデルに SomePropertyMaxLength というプロパティを作成し、MaxLength プロパティをそのプロパティにバインドすることです。

<TextBox Text="{Binding SomeProperty}" MaxLength="{Binding SomePropertyMaxLength}"/>
于 2012-01-05T15:52:36.807 に答える