我在Winforms应用中获得了WPF ElementHost
。用户控件有一些文本和TreeView
,它应显示应用程序提供的可用命令树。
我是WPF的新手(这是一项学习练习),因此在绑定数据方面存在一些问题。
我创建了一个CommandTreeViewModel
类来充当我的视图模型。它的FirstGeneration
属性为IEnumerable(of CommandViewModel)
。 CommandViewModel
类依次有一些描述Command
的简单属性,包括Children
属性(同样是IEnumerable(of CommandViewModel)
)。
我已经为我的WPF用户控件添加了Public Property ViewModel As CommandTreeViewModel
,该控件目前由我的winforms应用程序设置。
我不知道该怎么做是将我已经传递给ViewModel属性的数据并将其绑定到TreeView。 (有没有办法强力键入我的XAML Binding的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。
运行以上内容正确加载cotrol(我可以看到我的表单上的“测试”文本),但TreeView
仍为空白。没有错误被抛出。我假设这是因为我没有正确绑定数据。
最后,我还不清楚我的哪些属性需要DP?用户控件,ViewModel,模型儿童?我只是不清楚绑定是如何工作的。
答案 0 :(得分:1)
要解析的代码很多,我还没有在VB中编写一段时间,但我至少看到了一些东西。
我建议你稍微开始一点。如果你真的刚刚开始,那么首先尝试简单地绑定一些东西,而不是使用多级命令的树视图。在获取分层数据模板,添加样式(使用触发器!)等之前,尝试获取一个平面数据网格进行绑定。您将立即引入太多概念恕我直言。
我认为你根本不需要在这里使用依赖属性,除非我遗漏了什么。当您想要将usercontrol放入另一个控件/窗口并且能够通过XAML / Databinding控制属性时,主要使用依赖属性。
看起来您正在尝试通过依赖项属性设置viewModel。相反,只需在代码隐藏的构造函数中设置DataContext属性 - 类似于Me.DataContext = New CommandTreeViewModel(记住我的VB生锈:))。这可能是绑定不起作用的主要问题,实际上,因为View的DataContext没有设置。
最后,VS中的调试输出窗口应包含任何数据绑定错误,这对于确定绑定失败的位置有很大帮助。