У меня есть WPF ElementHost
в приложении Winforms. Пользовательский элемент управления имеет некоторый текст и TreeView
, который должен отображать дерево доступных команд, предоставляемых приложением.
Я новичок в WPF (это учебное упражнение), поэтому у меня возникли некоторые проблемы с привязкой данных.
Я создал CommandTreeViewModel
класс, который будет действовать как моя модель представления. Он имеет свойство FirstGeneration
, которое является IEnumerable(of CommandViewModel)
. Класс CommandViewModel
, в свою очередь, обладает некоторыми простыми свойствами, описывающими Command
, включая свойство Children
(снова IEnumerable(of CommandViewModel)
).
Я добавил Public Property ViewModel As CommandTreeViewModel
в свой пользовательский элемент управления WPF, который сейчас установлен моим приложением winforms.
Чего я не знаю, как это сделать, так это взять те данные, которые были переданы мне в свойстве ViewModel, и связать их с TreeView. (И есть ли способ строго напечатать класс ViewModel моего XAML Binding в стиле 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, Model Children? Мне просто непонятно, как работает привязка.