ElementHost
WinformsアプリにWPFがあります。ユーザーコントロールにはいくつかのテキストがありTreeView
、アプリによって提供される使用可能なコマンドのツリーを表示する必要があります。
私はWPF(これは学習演習です)を初めて使用するため、データのバインドに問題があります。
CommandTreeViewModel
ビューモデルとして機能するクラスを作成しました。であるFirstGeneration
プロパティがありIEnumerable(of CommandViewModel)
ます。次に、CommandViewModel
クラスには、プロパティをCommand
含めることを説明するいくつかの単純なプロパティがありChildren
ます(ここでもIEnumerable(of CommandViewModel)
)。
Public Property ViewModel As CommandTreeViewModel
今のところ、winformsアプリによって設定されるWPFユーザーコントロールにを追加しました。
方法がわからないのは、ViewModelプロパティで渡されたデータを取得し、それをTreeViewにバインドすることです。(そして、XAMLバインディングのViewModelクラスa-la MVCを強く入力する方法はありますか?)
必要に応じて、以下の適切なコードであると私が信じているものを含めました。
ユーザーコントロール
Public Class WPFCommandTree
Implements INotifyPropertyChanged
Public Property ViewModel As CommandTreeViewModel
Get
Return DirectCast(GetValue(ViewModelProperty), CommandTreeViewModel)
End Get
Set(ByVal value As CommandTreeViewModel)
If Not value.Equals(DirectCast(GetValue(ViewModelProperty), CommandTreeViewModel)) Then
SetValue(ViewModelProperty, value)
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("ViewModelProperty"))
End If
End Set
End Property
Public Shared ReadOnly ViewModelProperty As DependencyProperty = _
DependencyProperty.Register("ViewModel",
GetType(CommandTreeViewModel), GetType(Window),
New FrameworkPropertyMetadata(Nothing))
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
XAML
<UserControl x:Class="WPFCommandTree"
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="300" d:DesignWidth="300">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock FontSize="30" HorizontalAlignment="Center" VerticalAlignment="Center">Test</TextBlock>
<TreeView ItemsSource="{Binding FirstGeneration}"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch"
Grid.Row="1"
DataContext="{Binding}">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded"
Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected"
Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="FontWeight"
Value="Normal" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</UserControl>
モデルを表示
Public Class CommandTreeViewModel
Public Property RootCommand As CommandViewModel
Public Property FirstGeneration As ReadOnlyCollection(Of CommandViewModel)
Public Sub New(ByVal RootCommand As Command)
_RootCommand = New CommandViewModel(RootCommand)
_FirstGeneration = New ReadOnlyCollection(Of CommandViewModel)(New CommandViewModel() {_RootCommand})
End Sub
Public Sub New(ByVal RootCommand As CommandViewModel)
Me.RootCommand = RootCommand
Me.FirstGeneration = New ReadOnlyCollection(Of CommandViewModel)(New CommandViewModel() {_RootCommand})
End Sub
Public Sub New(ByVal RootCommands As IEnumerable(Of CommandViewModel))
Me.RootCommand = RootCommands.First
Me.FirstGeneration = New ReadOnlyCollection(Of CommandViewModel)(RootCommands.ToList)
End Sub
End Class
Public Class CommandViewModel
Implements INotifyPropertyChanged
Public Property Command As Command
Public Property Children As ReadOnlyCollection(Of CommandViewModel)
Public Property Parent As CommandViewModel
Public Property Name As String
Private Property _IsSelected As Boolean
Public Property IsSelected() As Boolean
Get
Return _isSelected
End Get
Set(ByVal value As Boolean)
If value <> _isSelected Then
_isSelected = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("IsSelected"))
End If
End Set
End Property
Private Property _IsExpanded As Boolean
Public Property IsExpanded() As Boolean
Get
Return _IsExpanded
End Get
Set(ByVal value As Boolean)
If value <> IsExpanded Then
_IsExpanded = value
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("IsExpanded"))
If _IsExpanded And _Parent IsNot Nothing Then
_Parent.IsExpanded = True
End If
End If
End Set
End Property
Public Sub New(ByVal Command As Command)
Me.New(Command, Nothing)
End Sub
Private Sub New(ByVal Command As Command, ByVal Parent As CommandViewModel)
_Command = Command
_Parent = Parent
If Command.Children IsNot Nothing AndAlso Command.Children.Count > 0 Then
_Children = New ReadOnlyCollection(Of CommandViewModel)(
Command.Children.Select(Function(x) New CommandViewModel(x, Me)
).ToList)
End If
End Sub
Public Event PropertyChanged(ByVal sender As Object, ByVal e As System.ComponentModel.PropertyChangedEventArgs) Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
End Class
ご覧のとおり、私は何をする必要があるのかはっきりしておらず、さまざまなチュートリアルからいくつかのコードを一緒にハックしようとしています。ほとんどはWPFのみです。
上記を実行すると、コントロールが正しくロードされますが(フォームに「テスト」テキストが表示されます)、TreeView
空白のままになります。エラーはスローされません。これは、データを正しくバインドしていないためだと思います。
最後に、どのプロパティがDPである必要があるのかもわかりません。ユーザーコントロール、ViewModel、モデルの子?バインディングがどのように機能するのかよくわかりません。