こんにちは私はデータグリッドを使用してwpfアプリを構築しています。パターンはモデルビュービューモデルです。
すべての画面にコンテンツコントロールが含まれており、適切なデータテンプレートを持つビューモデルを彼に割り当てるだけです。
とにかく、私の問題はコンボボックス列にあり、データコンテキストは提示されたエンティティであり、ビューモデルである必要があります。
最善の解決策は何ですか?
こんにちは私はデータグリッドを使用してwpfアプリを構築しています。パターンはモデルビュービューモデルです。
すべての画面にコンテンツコントロールが含まれており、適切なデータテンプレートを持つビューモデルを彼に割り当てるだけです。
とにかく、私の問題はコンボボックス列にあり、データコンテキストは提示されたエンティティであり、ビューモデルである必要があります。
最善の解決策は何ですか?
最終的に、コンボ ボックス リストごとに静的プロパティを持つクラスを作成しました。
(クラス自体を静的にすることはできません。そうしないと、XAML で開くことができなくなりますが、コンパイル エラーは発生しません)。
例えば:
public class ZoneList
{
private static readonly IList<Zone> _Items = new List<Zone>();
public static IList<Zone> Items
{
get { return _Items; }
}
}
次に、XAML で:
<UserControl.Resources>
<ResourceDictionary>
<ObjectDataProvider x:Key="myZoneList" ObjectType="{x:Type StaticLists:ZoneList}"/>
</ResourceDictionary>
</UserControl.Resources>
<ComboBox ItemsSource="{Binding Path=Items, Source={StaticResource myZoneList}}"></ComboBox>
別のデータグリッドを使用していますが、似ている可能性があります。私がやった方法は次のようなものでした:
XAML で、リソースに ObjectDataProvider を定義しました。
<ObjectDataProvider x:Key="VM" ObjectInstance="{x:Null}" x:Name="vm"/>
次に、DataContext (コンストラクターまたは DataContextChanged イベントのいずれか) を割り当てた後、次のようにしました。
(this.Resources["VM"] as ObjectDataProvider).ObjectInstance = this.DataContext;
Combobox xaml では、それをバインディング ソースとして使用しました。
ItemsSource="{Binding Source={StaticResource VM}, Path=SomeItems, Mode=OneWay}"
マイクロソフトのデータグリッドで機能するかどうかはわかりませんが、試してみる価値はあると思います.
これを実装する最良の方法は、グリッドで使用するすべてのルックアップに対していくつかの外部クラスを定義し、それらを静的リソースとしてテンプレートに埋め込むことであることがわかりました
これは私が ComboBoxes で ViewModel を使用した方法です。DataContext は ViewModel であり、基になるエンティティ (List<Person>) ではありません。
ViewModel (Person は Name と Age を持つ単純なクラスです):
public class PeopleViewModel : INotifyPropertyChanged
{
private List<Person> _peopleList;
private Person _selectedPerson;
public PeopleViewModel()
{
// initialize with sample data
_peopleList = getPeopleList();
}
// gets sample data
private List<Person> getPeopleList()
{
var result = new List<Person>();
for (int i = 0; i < 10; i++)
{
result.Add(new Person("person " + i, i));
}
return result;
}
public List<Person> PeopleList
{
get { return _peopleList; }
}
public Person SelectedPerson
{
get { return _selectedPerson; }
set
{
if (_selectedPerson == value) return;
_selectedPerson = value;
// required so that View know about changes
OnPropertyChanged("SelectedPerson");
}
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
// WPF will listen on this event for changes
public event PropertyChangedEventHandler PropertyChanged;
}
コンボ ボックスの XAML:
<ComboBox Name="cmbEnum" Width="150" ItemsSource="{Binding Path=PeopleList}" SelectedValue="{Binding Path=SelectedPerson}" SelectedValuePath="" DisplayMemberPath="Name" ></ComboBox>
そして、コードビハインドで私ができること:
public Window2()
{
InitializeComponent();
vm = new PeopleViewModel();
// we are listening on changes of ViewModel, not ComboBox
vm.PropertyChanged += new PropertyChangedEventHandler(vm_PropertyChanged);
this.DataContext = vm;
}
void vm_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "SelectedPerson")
{
MessageBox.Show(vm.SelectedPerson.Age.ToString());
}
}
// button1_Click should be probably replaced by Command
private void button1_Click(object sender, RoutedEventArgs e)
{
// sample showing that GUI is updated when ViewModel changes
vm.SelectedPerson = vm.PeopleList[2];
}
これが役に立てば幸いです。私はWPFを初めて使用します。これがMVVMを使用する正しい方法である場合、フィードバックを聞きたいです。コード内のViewModelとModel、およびViewのみを扱うので、非常にエレガントだと思います交換できます。