2 つのクラスで構成される非常に単純な複合モデルがあります。
Public Class ParentModelVM
Public Property Name As String
Public Property ChildModel As ChildModelVM
Public Sub New()
Name = "A Parent Model"
ChildModel = New ChildModelVM With {.Name = "A Child Model"}
End Sub
End Class
Public Class ChildModelVM
Public Property Name As String
Public Property Description As String
End Class
両方とも INotifyPropertyChanged を実装していますが、これは省略しています。ParentModelVM を編集するユーザー コントロールを作成しようとしています。
<UserControl x:Class="EditParentModel" .../>
<UserControl.DataContext>
<Binding RelativeSource="{RelativeSource Self}" Path="ViewModel" />
</UserControl.DataContext>
<TextBox Name="NameInput" Text="{Binding Path=Name}"/>
<local:EditChildModel x:Name="ChildModelInput" ViewModel="{Binding Path=ChildModel}"/>
</UserControl>
ViewModel は、既定で双方向にバインドする DependencyProperty として登録されている ParentModelVM です。タイプ ChildModelVM の ViewModel プロパティを持つ EditChildModel と呼ばれる同様の UserControl があり、デフォルトで双方向にバインドする DependencyProperty としても登録されています。
このロジックは私には理にかなっているようです。ParentModelVM には、Text プロパティがバインドされている TextBox コントロールで編集される文字列があり、ViewModel プロパティがバインドされている EditChildModel コントロールで編集される ChildModelVM があります。
ParentModelVM.Name はそのテキスト ボックスに正しくバインドされ、2 つの ChildViewModelVM プロパティはそれぞれのテキスト ボックスに正しくバインドされます。ただし、EditParentModel.ViewModel.ChildModel は EditChildModel.ViewModel と同じオブジェクトではなく、その理由がわかりません。ViewModel="{Binding Path=ChildModel}"
EditParentModel UserControl から属性を削除しても、アプリケーション全体の動作はまったく同じです。たとえば、NameInput は "A Parent Model" で初期化されますが、EditChildModel.NameInput は "A Child Model" で初期化されません。
これに関するヘルプは大歓迎です。ありがとう!
- 編集 -
わかりました、私はこれをばかげたことを超えて単純化しましたが、それでも機能しません。SimpleParent というモデルがあります。これはコード全体です:
Imports System.ComponentModel
Public Class SimpleParent
Implements INotifyPropertyChanged
Private _someText As String
Public Property SomeText As String
Get
Return _someText
End Get
Set(ByVal value As String)
_someText = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("SomeText"))
End Set
End Property
Public Sub New()
SomeText = "This is some text."
End Sub
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
テキストの代わりに「Says」と呼ばれる DependencyProperty を使用して、TextBox とまったく同じように機能する「SuperTextControl」と呼ばれる UserControl を作成しました。XAML 全体は次のとおりです。
<UserControl x:Class="SuperTextControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="23" d:DesignWidth="300">
<UserControl.DataContext>
<Binding RelativeSource="{RelativeSource Self}"/>
</UserControl.DataContext>
<TextBox Name="SaysInput" Text="{Binding Path=Says}" />
</UserControl>
コードビハインドは次のとおりです。
Public Class SuperTextControl
Public Shared ReadOnly SaysProperty As DependencyProperty =
DependencyProperty.Register("Says", GetType(String), GetType(SuperTextControl))
Public Property Says As String
Get
Return CTypeDynamic(Of String)(GetValue(SaysProperty))
End Get
Set(ByVal value As String)
SetValue(SaysProperty, value)
End Set
End Property
End Class
次に、SimpleParent DependencyProperty を持つ SimpleParentControl を作成しました。SimpleParent プロパティにバインドする他のコントロール内にこのコントロールを入れ子にする可能性があるため、DP として持っています。XAML 全体は次のとおりです。
<UserControl x:Class="SimpleParentControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfTest"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.DataContext>
<Binding RelativeSource="{RelativeSource Self}" Path="SimpleParent" />
</UserControl.DataContext>
<StackPanel>
<TextBox Text="{Binding Path=SomeText}" />
<local:SuperTextControl Says="{Binding Path=SomeText}" />
</StackPanel>
</UserControl>
そしてコードビハインド全体:
Public Class SimpleParentControl
Public Shared ReadOnly SimpleParentProperty As DependencyProperty =
DependencyProperty.Register("SimpleParent", GetType(SimpleParent), GetType(SimpleParentControl))
Public Property SimpleParent As SimpleParent
Get
Return CTypeDynamic(Of SimpleParent)(GetValue(SimpleParentProperty))
End Get
Set(ByVal value As SimpleParent)
SetValue(SimpleParentProperty, value)
End Set
End Property
Public Sub New()
' This call is required by the designer.
InitializeComponent()
' Add any initialization after the InitializeComponent() call.
SimpleParent = New SimpleParent()
End Sub
End Class
予想どおり、SimpleParentControl の TextBox に「This is some text」と表示されます。local:SuperTextControl には何も表示されません。これは、再利用可能な UserControl の作成について考えられる最も単純な例ですが、うまくいきません。確かに、再利用可能な UserControl をカスタム テキスト ボックスと同じくらい簡単に作成することに成功した人はいますが、これを行う方法について具体的に説明しているオンライン チュートリアルはありません。これは、一見理由もなく失敗する非常に些細な例です。これについての洞察をいただければ幸いです。ありがとう。