1

MVVM を使用していくつかの複雑な UserControls を設計しています。UserControls のデータ コンテキストは、すべてのロジックを処理し、UserControl インタラクションの結果をコントロールのコンシューマーに提供します。

私が直面している問題は、バインドに対して internal が機能しないように見え、パブリック バインディングではないソース プロパティにバインドしようとすると機能しないことです。VM top のすべてのソース プロパティを開いて (amek public) それらをバインドできるようにする必要がある場合は、UserControl とコンシューマーの内部を開きます。

  1. プロパティが使用するものについて混乱しています。
  2. 外部での使用を意図していないプロパティを使用して物事を壊す可能性があります。

何か案は?

前もって感謝します。

編集:これを見ると、ソースは常に公開されている必要があるようです。しかし、それでも内部を公開するという問題に直面しています。これに対する解決策はありますか?

例:

ジェネリック UserControl を作成します。コントロールは、エンドユーザーから提供されたクエリを取得し、クエリによって返された行を (何らかの方法で) 表示し、UserControl コンシューマーが選択した値を取得できるようにするブラックボックスである必要があります。コントロールは、行を表示する Combobox で実装されます。

UserControl は UserControl.xaml 内にあり、UserControl の ViewModel を含む UserControlVM.cs ファイルがあります。

ViewModel には、実行されるクエリ、クエリによって返される項目のリスト、および選択された項目が含まれます。アイテムのリストと選択されたアイテムは、UserControl にバインドできるように公開されます。

コンシューマーは、そのウィンドウ内で UserControl の 1 つのインスタンスを使用し、そのウィンドウ ビューモデル内で UserControlVM の 1 つのインスタンスを使用します。私が直面している問題は、エンドユーザーが、選択したアイテムにのみアクセスできる必要があるときに、クエリによって返されたアイテムのリストにアクセスできることです。

4

3 に答える 3

0

クラスのすべてのプロパティ ターゲットはBindingpublic である必要があります

可能な代替ソリューションは次のとおりです。

あなたDataContext(それが の場合ViewModel) は、実装する可能性がありINotifyPropertyChangedます。その場合は、 にDataContext( ViewModel)を設定するときUserControlに、イベント ハンドラーをサブスクライブし、PropertyChangedコード ビハインドにロジックを記述して、変更されたデータに応じてコントロールを操作します。

于 2012-04-10T11:21:20.913 に答える
0

私が見つけた1つの解決策(ただし、ViewModelにコンストラクターパラメーターが必要な場合は機能しません)。

  1. バインディング プロパティをパブリックに維持しながら、ViewModel を内部にします。
  2. ユーザーコントロールがエンドユーザーに提供するデータを含むクラス「UserControlData」を作成します
  3. UserControl 依存プロパティを介してそのクラスのインスタンスを提供します。
  4. ユーザー コントロールのコンシューマーは、そのビューモデルで UserControlData インスタンスをバインドして、ユーザー コントロールの結果を取得する必要があります。
于 2012-04-12T13:13:50.770 に答える
0

クラスへの実装の詳細であるデータは公開すべきではありませんが、私の意見では、とにかくこのタイプのデータにバインドする必要さえありません。ビューにバインドされるデータは、ビュー モデルのパブリック プロパティとコマンドである必要があります。ビューモデルはUI が 何であるかを定義することに注意してください。

ユーザー インターフェイスで変更が許可されていないパブリック プロパティは、セッターではなく、ゲッターのみを実装する必要があります。特定の条件下でのみ変更できるパブリック プロパティは、セッターでそれらの条件を適用する必要があります。ビューモデルは、すべての UI ロジック (プロパティとコマンド) を提供し、収容する必要があります。

また、そのすべてをテストする単体テストでビューモデルをラップする必要があります。

コメントのフィードバックに基づく更新:

class MyViewModel : ViewModelBase
{
     private bool _showSomething;
     public bool ShowSomething
     {
         get { return _showSomething; }
         set
         {
             _showSomething = value;
             RaisePropertyChanged("ShowSomething");
             RaisePropertyChanged("TheThing");
         }
     }

     public Something TheThing
     { 
         get
         {
             if(_showSomething) { return _theThing; }
             return _theOtherThing;
         }
     }

     private Something _theThing;
     private Something _theOtherThing;

}

編集*: 以下は、コメントに基づいて望ましいものに近い場合があります。

public interface IQueryControl
{
    string Query { get; set; } //view passes query in
    ReadOnlyCollection<string> QueryResultDescriptions { get; } //bind to combo items
    string SelectedQueryDescription { get; set; } //bind to combo selection
    object SelectedItem { get; } //resulting object
}

public class UserControlVM : ViewModelBase, IQueryControl
{
    private string _query;
    private ObservableCollection<object> _queryResults;
    private ReadOnlyCollection<string> _externalResults;
    private object _selectedResult;

    public string Query 
    { 
        get { return _query; } 
        set 
        {
            _query = value; 
            RaisePropertyChanged("Query");
            UpdateQueryResults(); 
        }
    }

    private void UpdateQueryResults()
    {
        //Do query which allocates / updates _queryResults;
        _externalResults = new ReadOnlyCollection<string>((from entry in _queryResults select entry.ToString()).ToList<string>());
        RaisePropertyChanged("QueryResultDescriptions");
    }

    public ReadOnlyCollection<string> QueryResultDescriptions
    {
        get { return _externalResults; }
    }

    public string SelectedQueryDescription
    {
        get { return _selectedResult.ToString(); }
        set
        {
            SelectResult(value);
        }
    }

    private void SelectResult(string value)
    {
        Dictionary<string, object> lookup = _queryResults.ToDictionary<object, string>((result) => { return result.ToString(); });
        if (lookup.ContainsKey(value))
        {
            _selectedResult = lookup[value];
            RaisePropertyChanged("SelectedQueryDescription");
            RaisePropertyChanged("SelectedItem");
        }
        else
        {
            //throw something
        }
    }

    public object SelectedItem
    {
        get { return _selectedResult; }
    }

}
于 2012-04-10T12:00:32.540 に答える