ネット上の複数のソースから、MVVM
では、ビューとビューモデルの間の通信/同期は依存関係プロパティを介して行われる必要があることがわかります。私がこれを正しく理解している場合、双方向バインディングを使用して、ビューの依存関係プロパティをビューモデルのプロパティにバインドする必要があります。現在、以前に同様の質問が行われていますが、十分な回答はありません。
このかなり複雑な問題の分析を始める前に、私の質問を次に示します。
customビューのDependencyProperty
をビューモデルのプロパティと同期するにはどうすればよいですか?
理想的な世界では、次のようにバインドするだけです。
<UserControl x:Class="MyModule.MyView" MyProperty="{Binding MyProperty}">
MyProperty
はUserControl
のメンバーではないため、これは機能しません。どー!私はさまざまなアプローチを試しましたが、どれも成功しませんでした。
1つの解決策は、上記を機能させるために必要な依存関係プロパティを含む基本クラスUserControlEx
を定義することです。ただし、これはすぐに非常に複雑になります。十分じゃない!
ViewからViewModelを分離するためにCaliburn.Microを使用します。それでも、MVVMでは同じように機能する可能性があります。 MVVMもビューのDataContext
プロパティをViewModelのインスタンスに設定すると思います。
// in the class of the view: MyView
public string ViewModelString // the property which stays in sync with VM's property
{
get { return (string)GetValue(ViewModelStringProperty); }
set
{
var oldValue = (string) GetValue(ViewModelStringProperty);
if (oldValue != value) SetValue(ViewModelStringProperty, value);
}
}
public static readonly DependencyProperty ViewModelStringProperty =
DependencyProperty.Register(
"ViewModelString",
typeof(string),
typeof(MyView),
new PropertyMetadata(OnStringValueChanged)
);
private static void OnStringValueChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
// do some custom stuff, if needed
// if not, just pass null instead of a delegate
}
public MyView()
{
InitializeComponent();
// This is the binding, which binds the property of the VM
// to your dep. property.
// My convention is give my property wrapper in the view the same
// name as the property in the VM has.
var nameOfPropertyInVm = "ViewModelString"
var binding = new Binding(nameOfPropertyInVm) { Mode = BindingMode.TwoWay };
this.SetBinding(SearchStringProperty, binding);
}
// in the class of the ViewModel: MyViewModel
public string ViewModelStringProperty { get; set; }
この種の実装は、INotifyPropertyChanged
インターフェースの実装を完全に欠いていることに注意してください。このコードを適切に更新する必要があります。
XAMLでそれを実行したい場合は、スタイルを使用してそれを実現してみることができます。
次に例を示します。
<UserControl x:Class="MyModule.MyView"
xmlns:local="clr-namespace:MyModule">
<UserControl.Resources>
<Style TargetType="local:MyView">
<Setter Property="MyViewProperty" Value="{Binding MyViewModelProperty, Mode=TwoWay}"/>
</Style>
</UserControl.Resources>
<!-- content -->
</UserControl>
あなたの場合、MyViewProperty
とMyViewModelProperty
はどちらもMyProperty
という名前になりますが、何が何であるかを明確にするために、異なる名前を使用しました。
ViewでDependencyProperty "DepProp"を定義し、ViewModelでまったく同じ値を使用したいとします(INotifyPropertyChangedを実装しますが、DependencyObjectは実装しません)。 XAMLで次のことができるはずです。
<UserControl x:Class="MyModule.MyView"
xmlns:local="clr-namespace:MyModule"
x:Name="Parent">
<Grid>
<Grid.DataContext>
<local:MyViewModel DepProp="{Binding ElementName=Parent, Path=DepProp}"/>
</Grid.DataContext>
...
</Grid>
</UserControl>