1

MVVM を使用して ListBox の項目を ViewModel にバインドする際の規則はありますか?

以下の XAML では、ボタンの ListBox を作成しています。ListBox は、ViewModel からの監視可能なコレクションにバインドされています。次に、ボタンの Command プロパティを ICommand にバインドします。問題は、そのバインドを追加すると、ViewModel ではなくデータ オブジェクトに対してバインドされることです。

MyListOfDataObjects プロパティを ViewModel のリストに変更するだけですか? もしそうなら、どこでそれらの新しいオブジェクトをインスタンス化しますか? いくつかの依存関係があるため、依存関係の挿入を使用することをお勧めします。GetData ラムダを変更しますか?

一般的に、ここで良い習慣と見なされるものは何ですか? この状況の例は見つかりませんでしたが、かなり一般的だと思います。

私は MVVMLight フレームワークを使用していますが、他のフレームワークも検討したいと考えています。

<Window x:Class="KeyMaster.MainWindow"
        DataContext="{Binding Main, Source={StaticResource Locator}}">

    <Window.Resources>
        <ResourceDictionary>
            <DataTemplate x:Key="MyDataTemplate">
                <Button Command="{Binding ButtonPressedCommand}"
                        CommandParameter="{Binding .}"
                        Content="{Binding Name}" />
            </DataTemplate>
        </ResourceDictionary>
    </Window.Resources>

    <Grid x:Name="LayoutRoot">
        <ListBox ItemsSource="{Binding MyListOfDataObjects}"
                 ItemTemplate="{StaticResource MyDataTemplate}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal"
                                IsItemsHost="True" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ListBox>
    </Grid>
</Window>

標準の MVVMLight ViewModel を使用しています。

using GalaSoft.MvvmLight;
using KeyMaster.Model;
using System.Collections.ObjectModel;

namespace KeyMaster.ViewModel
{
    public class MainViewModel : ViewModelBase
    {
        private readonly IDataService _dataService;
        private ObservableCollection<MyData> _myListOfDataObjects;

        public MainViewModel(IDataService dataService)
        {
            _dataService = dataService;
            _dataService.GetData(
                (item, error) =>
                {
                    if (error != null)
                    {
                        return;
                    }

                    MyListOfDataObjects = new ObservableCollection<MyData>(item);
                });
        }

        public ObservableCollection<MyData> MyListOfDataObjects
        {
            get { return _myListOfDataObjects; }
            set
            {
                if (_myListOfDataObjects == value) return;

                _myListOfDataObjects = value;
                RaisePropertyChanged(() => MyListOfDataObjects);
            }
        }
    }
}

ありがとう。

4

2 に答える 2

0

MVVM では、生データ (モデルとも呼ばれます) と ViewModel の間に明確な分離があります。ViewModel は、ビューにデータを渡す前に、データを解析し、必要な形式に変更することさえ担当します。

簡単な例として、Model を XML として保持し、ViewModel でそれを解析して、各要素から特定のプロパティ (" Name" など) のみを取得し、それらをリストに追加します。このリストのみがビューに表示されます。

そうは言っても、私がどこに向かっているのかがわかると思います-コマンドはモデルではなくビューモデルにある必要があります。ご自身で述べたように、VM とモデルの両方からできるだけ多くの UI ロジックを除外する必要があります。

特定のタイプのデータに対して特定のことを行う特定のコマンドがある場合、それをより「一般的な」タイプの ViewModel で使用することができます。 を使用しCanExectueて、特定のケースでのみこのコマンドを許可できます。それでも、コマンドは ViewModel に配置する必要があります。

あなたの特定のケースでは、ViewModel でコマンドを使用しても問題はありません。発生すると、データに対して必要なことは何でも実行されます。ViewModel のリストは必要ありません。必要なのは 1 つだけです。

于 2013-01-02T08:46:29.550 に答える
0

ボタンを押す機能が必要な場所に依存すると思います。それが常に MyData オブジェクトに関連している場合、(可能であれば) コマンドを MyData オブジェクトに入れるのは適切ではないでしょうか? (ps。ビューに関連付けられていないため、コマンドプロパティを追加しているという理由だけで、MyDataオブジェクトをViewModelsとは呼びません)

または、VM でコマンドが必要な場合は、ウィンドウのデータコンテキストを使用してコマンドをバインドしてみてください。つまり、次のようなものです。

<Button Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.ButtonPressedCommand}"
                    CommandParameter="{Binding .}"
                    Content="{Binding Name}" />

私は過去にそれで問題を抱えていましたが、個々のオブジェクトにコマンドを追加しました。

于 2013-01-02T00:13:12.913 に答える