値コンバーターは価値がある以上に問題がありますか?


20

多数の値の変換を必要とするビューを持つWPFアプリケーションに取り組んでいます。当初、私の哲学(XAML Disciplesに関するこの活発な議論に一部影響を受けました)は、ビューのデータ要件のサポートについて厳密にビューモデルを作成することでした。つまり、データを可視性、ブラシ、サイズなどに変換するために必要な値の変換は、値コンバーターと多値コンバーターで処理されます。概念的には、これは非常にエレガントに見えました。ビューモデルとビューの両方に明確な目的があり、うまく分離されます。「データ」と「外観」の間に明確な線が引かれます。

まあ、この戦略を「古い大学の試み」にした後、私はこの方法で開発を続けたいかどうか疑問に思っています。私は実際に、値コンバーターをダンプし、(ほとんど)すべての値変換の責任をビューモデルの手に直接置くことを強く考えています。

値コンバータを使用する現実は、明確に分離された懸念の見かけの価値まで測定しているようには見えません。値コンバーターの最大の問題は、使用するのが面倒なことです。新しいクラスを作成し、実装するIValueConverterIMultiValueConverter、値をobject適切な型にキャストし、DependencyProperty.Unset(少なくとも多値コンバーターの場合)テストし、変換ロジックを記述し、コンバーターをリソースディクショナリに登録する必要があります [下記の更新を参照]、最後に、かなり冗長なXAMLを使用してコンバーターを接続します(バインディングとコンバーターの名前の両方にマジックストリングを使用する必要があります)[以下の更新を参照])。特にVisual Studioのデザインモード/ Expression Blendでは、エラーメッセージはしばしば不可解であるため、デバッグプロセスもピクニックではありません。

これは、すべての価値変換を担当するビューモデルを作成するという代替策が改善であると言っているわけではありません。これは、草が反対側でより緑であるという問題である可能性が非常に高い。関心事のエレガントな分離を失うことに加えて、派生プロパティの束を記述し、RaisePropertyChanged(() => DerivedProperty)ベースプロパティを設定する際に慎重に呼び出す必要があります。これは、不快なメンテナンスの問題であることがわかります。

以下は、ビューモデルに変換ロジックを処理させ、値コンバーターを廃止することの長所と短所をまとめた最初のリストです。

  • 長所:
    • マルチコンバーターが排除されるため、総バインディング数が少なくなります
    • 少ないマジックストリング(バインディングパス+コンバーターリソース名
    • 各コンバータを登録する必要はありません(さらにこのリストを維持します)
    • 各コンバーターを作成する作業が少なくなります(インターフェイスの実装やキャストは不要)
    • 変換に役立つ依存関係を簡単に挿入できます(例:カラーテーブル)
    • XAMLマークアップは冗長ではなく、読みやすい
    • コンバーターの再利用は引き続き可能です(ただし、ある程度の計画が必要です)
    • DependencyProperty.Unsetに不可解な問題はありません(複数値コンバーターで気づいた問題)

*取り消し線は、マークアップ拡張機能を使用すると消える利点を示しています(以下の更新を参照)

  • 短所:
    • ビューモデルとビューの間のより強い結合(たとえば、プロパティは可視性やブラシなどの概念を処理する必要があります)
    • ビュー内のすべてのバインディングの直接マッピングを可能にする、より多くのプロパティ
    • RaisePropertyChanged派生プロパティごとに呼び出す必要があります(以下の更新2を参照)
    • 変換がUI要素のプロパティに基づいている場合、コンバーターに依存する必要があります

おそらくおわかりのように、この問題については胸焼けがあります。私は、リファクタリングの道を進むのを非常にためらっていますが、値変換を使用するか、ビューモデルで多数の値変換プロパティを公開するかどうかにかかわらず、コーディングプロセスが同じように非効率的で退屈です。

賛否両論ありませんか?価値変換の両方の手段を試した人にとって、あなたにとってどちらがより効果的であると思いましたか?他の選択肢はありますか?(弟子たちは、タイプ記述子プロバイダーについて何かを言及しましたが、彼らが話していることを理解できませんでした。これについての洞察はありがたいです。)


更新

本日、「マークアップ拡張機能」と呼ばれるものを使用して、値コンバーターを登録する必要をなくすことができることを発見しました。実際、これらを登録する必要がなくなるだけでなく、を入力しConverter=たときにコンバーターを選択するためのインテリセンスが実際に提供されます。:ここでは私が始まった記事ですhttp://www.wpftutorial.net/ValueConverters.htmlが

マークアップ拡張機能を使用する機能により、上記の長所と短所のリストと議論のバランスが多少変わります(取り消し線を参照)。

この啓示の結果として、私はハイブリッド私がコンバータを使用するシステムで実験てるBoolToVisibilityと私は呼んでMatchToVisibility、他のすべての変換のためのビューモデル。MatchToVisibilityは基本的に、バインドされた値(通常は列挙型)がXAMLで指定された1つ以上の値と一致するかどうかを確認できるコンバーターです。

例:

Visibility="{Binding Status, Converter={vc:MatchToVisibility
            IfTrue=Visible, IfFalse=Hidden, Value1=Finished, Value2=Canceled}}"

基本的にこれは、ステータスが終了またはキャンセルのいずれかであるかを確認します。そうである場合、可視性は「可視」に設定されます。それ以外の場合、「非表示」に設定されます。これは非常に一般的なシナリオであることが判明し、このコンバーターを使用すると、ビューモデルの約15個のプロパティ(および関連するRaisePropertyChangedステートメント)が節約されました。を入力するとConverter={vc:、「MatchToVisibility」がインテリセンスメニューに表示されることに注意してください。これにより、エラーの可能性が著しく減少し、値コンバーターの使用が面倒になりにくくなります(必要な値コンバーターの名前を覚えたり検索したりする必要がなくなります)。

興味があれば、以下のコードを貼り付けます。この実装の一つの重要な特徴は、MatchToVisibilityそれがバインドされた値であるかどうかをチェックしていることでenum、それがあれば、それはチェックを確認するためにValue1Value2なども同じ型の列挙型です。これにより、列挙値のいずれかが誤って入力されているかどうかの設計時および実行時チェックが提供されます。これをコンパイル時のチェックに改善するには、代わりに以下を使用できます(手で入力したので、間違えた場合はご容赦ください):

Visibility="{Binding Status, Converter={vc:MatchToVisibility
            IfTrue={x:Type {win:Visibility.Visible}},
            IfFalse={x:Type {win:Visibility.Hidden}},
            Value1={x:Type {enum:Status.Finished}},
            Value2={x:Type {enum:Status.Canceled}}"

これは安全ですが、私にとっては価値がありません。これを行う場合は、ビューモデルのプロパティを使用することもできます。とにかく、デザイン時のチェックはこれまでに試したシナリオに完全に適していることがわかりました。

ここにコードがあります MatchToVisibility

[ValueConversion(typeof(object), typeof(Visibility))]
public class MatchToVisibility : BaseValueConverter
{
    [ConstructorArgument("ifTrue")]
    public object IfTrue { get; set; }

    [ConstructorArgument("ifFalse")]
    public object IfFalse { get; set; }

    [ConstructorArgument("value1")]
    public object Value1 { get; set; }

    [ConstructorArgument("value2")]
    public object Value2 { get; set; }

    [ConstructorArgument("value3")]
    public object Value3 { get; set; }

    [ConstructorArgument("value4")]
    public object Value4 { get; set; }

    [ConstructorArgument("value5")]
    public object Value5 { get; set; }

    public MatchToVisibility() { }

    public MatchToVisibility(
        object ifTrue, object ifFalse,
        object value1, object value2 = null, object value3 = null,
        object value4 = null, object value5 = null)
    {
        IfTrue = ifTrue;
        IfFalse = ifFalse;
        Value1 = value1;
        Value2 = value2;
        Value3 = value3;
        Value4 = value4;
        Value5 = value5;
    }

    public override object Convert(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        var ifTrue = IfTrue.ToString().ToEnum<Visibility>();
        var ifFalse = IfFalse.ToString().ToEnum<Visibility>();
        var values = new[] { Value1, Value2, Value3, Value4, Value5 };
        var valueStrings = values.Cast<string>();
        bool isMatch;
        if (Enum.IsDefined(value.GetType(), value))
        {
            var valueEnums = valueStrings.Select(vs => vs == null ? null : Enum.Parse(value.GetType(), vs));
            isMatch = valueEnums.ToList().Contains(value);
        }
        else
            isMatch = valueStrings.Contains(value.ToString());
        return isMatch ? ifTrue : ifFalse;
    }
}

ここにコードがあります BaseValueConverter

// this is how the markup extension capability gets wired up
public abstract class BaseValueConverter : MarkupExtension, IValueConverter
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }

    public abstract object Convert(
        object value, Type targetType, object parameter, CultureInfo culture);

    public virtual object ConvertBack(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

これがToEnum拡張メソッドです

public static TEnum ToEnum<TEnum>(this string text)
{
    return (TEnum)Enum.Parse(typeof(TEnum), text);
}

更新2

この質問を投稿してから、プロパティと依存プロパティにNotifyPropertyChangedコードを挿入するために「ILウィービング」を使用するオープンソースプロジェクトに出会いました。これにより、ビューモデルの「ステロイドの値コンバーター」としてのジョシュスミスのビジョンの実装が非常に簡単になります。「自動実装プロパティ」を使用するだけで、ウィーバーが残りを行います。

例:

このコードを入力すると:

public string GivenName { get; set; }
public string FamilyName { get; set; }

public string FullName
{
    get
    {
        return string.Format("{0} {1}", GivenName, FamilyName);
    }
}

...これがコンパイルされます:

string givenNames;
public string GivenNames
{
    get { return givenName; }
    set
    {
        if (value != givenName)
        {
            givenNames = value;
            OnPropertyChanged("GivenName");
            OnPropertyChanged("FullName");
        }
    }
}

string familyName;
public string FamilyName
{
    get { return familyName; }
    set 
    {
        if (value != familyName)
        {
            familyName = value;
            OnPropertyChanged("FamilyName");
            OnPropertyChanged("FullName");
        }
    }
}

public string FullName
{
    get
    {
        return string.Format("{0} {1}", GivenName, FamilyName);
    }
}

これにより、入力、読み取り、過去のスクロールなどのコード量を大幅に節約できます。さらに重要なことは、依存関係を把握する必要がなくなることです。呼び出しFullNameを追加するために苦労して依存関係のチェーンをさかのぼることなく、新しい「プロパティ取得」を追加できRaisePropertyChanged()ます。

このオープンソースプロジェクトとは何ですか?元のバージョンは「NotifyPropertyWeaver」と呼ばれますが、所有者(Simon Potter)は一連のILウィーバーをホストするための「Fody」と呼ばれるプラットフォームを作成しました。この新しいプラットフォームでのNotifyPropertyWeaverに相当するものは、PropertyChanged.Fodyと呼ばれます。

  • Fodyのセットアップ手順: http ://code.google.com/p/fody/wiki/SampleUsage(「Virtuosity」を「PropertyChanged」に置き換えます
  • PropertyChanged.Fodyプロジェクトサイト: http : //code.google.com/p/propertychanged/

NotifyPropertyWeaver(インストールは少し簡単ですが、バグ修正以外に将来更新される必要はありません)を使用したい場合は、プロジェクトサイトhttp://code.google.com/p/をご覧 ください。 notifypropertyweaver /

いずれにせよ、これらのILウィーバーソリューションは、ステロイドと値コンバーターのビューモデル間の議論の計算を完全に変更します。


注:BooleanToVisibility可視性に関連する1つの値(true / false)を取得し、それを別の値に変換します。これは、の理想的な使用のようValueConverterです。一方、MatchToVisibilityビジネスロジックをエンコードするView(表示するアイテムの種類)。私の意見では、この論理はViewModel、私が呼んでいるものにプッシュされるべきEditModelです。ユーザーが見ることができるのは、テスト対象のものです。
スコットホイットロック

@Scott、それは良い点です。私が現在取り組んでいるアプリは、実際には「ビジネス」アプリではなく、ユーザーごとに異なるアクセス許可レベルがあるため、これらの方針に沿って考えていませんでした。MatchToVisibility(私はオンとオフを切り替えることができる部品のトンで、特に1つのビューを持っている。ほとんどの場合、ビューのセクションがさえて(ラベル付けされているいくつかの簡単なモード切り替えを可能にするための便利な方法と思われたx:Nameモードに合わせて)これは「ビジネスロジック」であるとは思いもしませんでしたが、あなたのコメントに少し考えてみます。
-devuxer

例:ラジオ、CD、またはMP3モードのステレオシステムがあるとします。UIのさまざまな部分に各モードに対応するビジュアルがあると仮定します。(1)どのグラフィックがどのモードに対応するかをビューに決定させ、それに応じてオン/オフを切り替える、(2)各モード値のビューモデルのプロパティを公開する(例:IsModeRadio、IsModeCD)、または(3)公開する各グラフィカル要素/グループのビューモデルのプロパティ(IsRadioLightOn、IsCDButtonGroupOnなど)。(1)既にモードを認識しているため、私の見解に自然にフィットしているように見えました。この場合、どう思いますか?
-devuxer

これは最も長い質問です。SE全体でこれまで見たことがあります。:]
trejder 14

回答:


10

私はValueConvertersいくつかのケースで使用しViewModel、他のロジックを入れました。私の感覚では、a ValueConverterViewレイヤーの一部になるので、ロジックが本当にその一部であるView場合はそこに配置し、そうでない場合はに配置しViewModelます。

私のアプリケーションでは、のテスト可能なバインド可能な表面としてのみ存在するため、個人的にはesのような特定の概念ViewModelを扱うことに問題はありません。ただし、一部の人々は多くのビジネスロジックを配置します(私はしません)。その場合は、ビジネスレイヤーの一部に似ているため、その場合は、WPF固有の要素は必要ありません。ViewBrushViewModelViewViewModelViewModel

私は別の分離を好む:

  • View- WPFのもの、時にはテスト不能(XAMLとコードビハインドのような)もValueConverter
  • ViewModel -WPF固有のテスト可能でバインド可能なクラス
  • EditModel -操作中のモデルを表すビジネスレイヤーの一部
  • EntityModel -永続的なモデルを表すビジネスレイヤーの一部
  • Repository- EntityModelデータベースへの永続化の責任

だから、私はそれを行う方法は、私ははほとんど使用していValueConverter

私があなたの「詐欺師」から逃れた方法は、私のViewModel「非常に一般的な」ことです。たとえば、ViewModel私が持っているものは、ChangeValueViewModelLabelプロパティとValueプロパティを実装しています。でViewありますLabelことLabelプロパティに結合し、TextBoxそのValueプロパティにバインドします。

次に、タイプからキーオフされたChangeValueViewを持っています。WPFは、それが適用されると判断するたびに。myのコンストラクターは、状態を更新するために必要な対話ロジック(通常は単にを渡す)と、ユーザーが値を編集するときに実行する必要があるアクション(でいくつかのロジックを実行するだけ)を取ります。DataTemplateChangeValueViewModelViewModelViewChangeValueViewModelEditModelFunc<string>ActionEditModel

ViewModel(画面用の)親EditModelは、コンストラクタでを受け取り、ViewModelなどの適切な要素をインスタンス化しますChangeValueViewModel。親ViewModelは、ユーザーが変更を行ったときに実行するアクションを注入しているため、これらのアクションをすべてインターセプトし、他のアクションを実行できます。したがって、に挿入される編集アクションは次のChangeValueViewModelようになります。

(string newValue) =>
{
    editModel.SomeField = newValue;
    foreach(var childViewModel in this.childViewModels)
    {
        childViewModel.RefreshStateFromEditModel();
    }
}

明らかにforeachループは他の場所でリファクタリングできますが、これはアクションを実行してモデルに適用し、(モデルが何らかの未知の方法で状態を更新したと仮定して)すべての子ViewModelに移動して状態を取得するよう指示します再びモデル。状態が変更された場合、PropertyChanged必要に応じてイベントを実行する責任があります。

これは、たとえばリストボックスと詳細パネルの間の相互作用を非常にうまく処理します。ユーザーが新しい選択肢を選択するEditModelと、その選択肢でが更新EditModelされ、詳細パネルに公開されるプロパティの値が変更されます。ViewModel自動的に、彼らは新しい値をチェックする必要があることを通知し、彼らが変更した場合、彼らは彼らの火を取得詳細パネル情報の表示を担当している子どもたちPropertyChangedのイベントを。


/ nod。それは私の見た目とかなり似ています。
イアン

+1。答えてくれてありがとう、スコット、私はあなたと同じレイヤーを持っています。また、ビューモデルにビジネスロジックを入れません。(記録のために、私はEntityFramework Code Firstを使用しており、ビューモデルとエンティティモデル間で変換するサービスレイヤーがあります。逆もまた同様です。)すべて/ほとんどの変換ロジックをビューモデルレイヤーに配置します。
-devuxer

@DanM-はい、同意します。ViewModelレイヤーでの変換を希望します。誰もが私に同意するわけではありませんが、それはあなたのアーキテクチャがどのように機能するかに依存します。
スコットホイットロック

2
最初の段落を読んだ後で+1と言いましたが、2番目の段落を読んで、ViewModelsにビュー固有のコードを配置することに強く反対します。ViewModelには、(のような一般的なビューの後ろに行くために特別に作成された場合は、1つの例外があるCalendarViewModelためCalendarView、ユーザーコントロール、またはDialogViewModelのためにDialogView)。それは私の意見です:)
レイチェル

@レイチェル-まあ、もしあなたが私の2番目のパラグラフを過ぎて読み続けていたら、それがまさに私がやっていたことだとわかるでしょう。:)私ViewModelのビジネスロジックはありません。
スコットホイットロック

8

オブジェクトの可視性の決定、表示する画像の決定、使用するブラシの色の決定など、変換がビュー関連のものである場合、常にコンバーターをビューに配置します。

フィールドをマスクする必要があるかどうかを判断するなどのビジネス関連の場合、またはユーザーにアクションを実行する権限がある場合、ViewModelで変換が行われます。

あなたの例から、あなたは大きなWPFを欠いていると思います:DataTriggers。条件値を決定するためにコンバーターを使用しているように見えますが、コンバーターは実際にあるデータ型を別のデータ型に変換するためのものでなければなりません。

上記の例では

例:ラジオ、CD、またはMP3モードのステレオシステムがあるとします。UIのさまざまな部分に各モードに対応するビジュアルがあると仮定します。(1)どのグラフィックがどのモードに対応するかをビューに決定させ、それに応じてオン/オフを切り替える、(2)各モード値のビューモデルのプロパティを公開する(例:IsModeRadio、IsModeCD)、または(3)公開する各グラフィカル要素/グループのビューモデルのプロパティ(IsRadioLightOn、IsCDButtonGroupOnなど)。(1)既にモードを認識しているため、私の見解に自然にフィットしているように見えました。この場合、どう思いますか?

を使用して、DataTrigger表示する画像を決定しますConverter。コンバーターは、あるデータ型を別のデータ型に変換するためのものであり、トリガーは値に基づいて一部のプロパティを決定するために使用されます。

<Style x:Key="RadioImageStyle">
    <Setter Property="Source" Value="{StaticResource RadioImage}" />
    <Style.Triggers>
        <DataTrigger Binding="{Binding Mode}" Value="CD">
            <Setter Property="Source" Value="{StaticResource CDImage}" />
        </DataTrigger>
        <DataTrigger Binding="{Binding Mode}" Value="MP3">
            <Setter Property="Source" Value="{StaticResource MP3Image}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

このためにConverterの使用を検討するのは、バインドされた値に実際に画像データが含まれていて、UIが理解できるデータ型に変換する必要がある場合だけです。たとえば、データソースにというプロパティが含まれてImageFilePathいる場合、コンバータを使用して画像ファイルの場所を含む文字列を、画像BitmapImageのソースとして使用できるものに変換することを検討します

<Style x:Key="RadioImageStyle">
    <Setter Property="Source" Value="{Binding ImageFilePath, 
            Converter={StaticResource StringPathToBitmapConverter}}" />
</Style>

最終結果として、あるデータ型を別のデータ型に変換する汎用コンバーターでいっぱいのライブラリ名前空間が1つあり、新しいコンバーターをコーディングする必要はほとんどありません。特定の変換用のコンバーターが必要になる場合がありますが、それらはあまり頻繁ではないので、それらを作成してもかまいません。


+1。良い点をいくつか挙げます。以前にトリガーを使用したことがありますが、私の場合は、イメージソース(プロパティ)を切り替えず、Grid要素全体を切り替えています。また、ビューモデルのデータと構成ファイルで定義された特定のカラーパレットに基づいて、前景/背景/ストロークのブラシを設定するなどのことも試みています。これがトリガーまたはコンバーターのどちらに適しているかはわかりません。ビューモデルにほとんどのビューロジックを配置することに関してこれまでに抱えている唯一の問題は、すべてのRaisePropertyChanged()呼び出しを配線することです。
devuxer

@DanM実際にはaでこれらすべてをDataTrigger行い、Gridの要素を切り替えます。通常ContentControl、動的コンテンツがあるべき場所に配置ContentTemplateし、トリガーでスワップアウトします。私はあなたが(のヘッダを持つセクションまでスクロール興味があるなら、以下のリンクでの例を持っているUsing a DataTriggerrachel53461.wordpress.com/2011/05/28/...
レイチェル

以前にデータテンプレートとコンテンツコントロールを使用したことがありますが、常に各ビューに一意のビューモデルがあったため、トリガーは必要ありませんでした。とにかく、あなたのテクニックは完璧に理にかなっており、非常にエレガントですが、非常に冗長でもあります。:MatchToVisibilityで、それはこれに短縮することができ<TextBlock Text="I'm a Person" Visibility={Binding ConsumerType, Converter={vc:MatchToVisibility IfTrue=Visible, IfFalse=Hidden, Value1=Person}}"、および<TextBlock Text="I'm a Business" Visibility={Binding ConsumerType, Converter={vc:MatchToVisibility IfTrue=Visible, IfFalse=Hidden, Value1=Business}}"
devuxer

1

どちらかといえば、テストしているものに依存します

テストなし:ViewModelと任意のViewModelを混在させます(後でいつでもリファクタリングできます)。
ViewModel以下でのテスト:コンバーターを使用します。
モデルレイヤー以下でのテスト:ビューモデルとビューモデルの混在

ViewModelは、ViewのModelを抽象化します。個人的には、ブラシなどにViewModelを使用し、コンバーターをスキップします。 データが「最も純粋な」形式(つまり、モデルレイヤー)であるレイヤーでテストします。


2
テストに関する興味深い点ですが、ビューモデルにコンバーターロジックがあると、ビューモデルのテスト容易性がどのように損なわれるかわかりません。確かに、ビューモデルに実際のUI コントロールを配置することはお勧めしません。ただ、ビュー固有のプロパティが好きVisibilitySolidColorBrushThickness
devuxer

@DanM:View-firstアプローチを使用している場合、問題ありません。ただし、ViewModelがViewを参照するViewModel-firstアプローチを使用している場合、問題ある可能性があります。
ジェイクバーガー

やあジェイ、間違いなくビューファーストのアプローチ。ビューは、バインドする必要があるプロパティの名前を除いて、ビューモデルについて何も知りません。フォローアップしていただきありがとうございます。+1。
-devuxer

0

これはおそらくあなたが言及したすべての問題を解決するわけではありませんが、考慮すべき2つのポイントがあります。

最初に、コンバーターコードを最初の戦略のどこかに配置する必要があります。ビューまたはビューモデルのその部分を考慮しますか?ビューの一部である場合は、ビューモデルではなくビュー固有のプロパティをビューに配置してみませんか?

第二に、非コンバーター設計が、すでに存在する実際のオブジェクトのプロパティを変更しようとするように聞こえます。既にINotifyPropertyChangedを実装しているように聞こえるので、ビュー固有のラッパーオブジェクトを作成してバインドするのはなぜですか。以下に簡単な例を示します。

public class RealData
{
    private bool mIsInteresting;
    public bool IsInteresting
    {
        get { return mIsInteresting; }
        set 
        {
            if (mIsInteresting != null) 
            {
                mIsInteresting = value;
                RaisePropertyChanged("IsInteresting");
            }
        }
    }
}

public class RealDataView
{
    private RealData mRealData;

    public RealDataView(RealData data)
    {
        mRealData = data;
        mRealData.PropertyChanged += OnRealDataPropertyChanged;
    }

    public Visibility IsVisiblyInteresting
    {
       get { return mRealData.IsInteresting ? Visibility.Visible : Visibility.Hidden; }
       set { mRealData.IsInteresting = (value == Visibility.Visible); }
    }

    private void OnRealDataPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (e.PropertyName == "IsInteresting") 
        {
            RaisePropertyChanged(this, "IsVisiblyInteresting");
        }
    }
}

ビューまたはビューモデルでエンティティモデルのプロパティを直接変更していることを意味するつもりはありませんでした。ビューモデルは間違いなく、エンティティモデルレイヤーとは異なるレイヤーです。実際、これまでに行った作業は読み取り専用ビューでした。これは、アプリケーションに編集が含まれないということではありませんが、編集に使用されるコントロールで変換が行われることはありません(したがって、リスト内の選択を除き、すべてのバインディングが一方向であると想定します)。ただし、「データビュー」についての良い点です。それは、質問の冒頭で言及したXAMLの弟子の投稿で提起された概念でした。
-devuxer

0

仮想化を活用するために値コンバーターを使用するとよい場合があります。

この例は、グリッド内の数十万のセルのビットマスクされたデータを表示する必要があったプロジェクトでのことです。すべてのセルのビューモデルでビットマスクをデコードすると、プログラムのロードに時間がかかりすぎました。

しかし、単一のセルをデコードする値コンバーターを作成したとき、プログラムはほんの少しの時間でロードされ、ユーザーが特定のセルを見ているときにのみコンバーターが呼び出されるため、応答性も高くなりました(呼び出す必要があるだけです)ユーザーがグリッド上でビューを移動するたびに最大30回)。

このソリューションがMVVMにどのように不満を抱いているのかわかりませんが、ロード時間を95%削減しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.