【发布时间】:2023-01-28 00:38:26
【问题描述】:
我的 WPF MVVM VB.NET 应用程序在开始时将歌曲列表加载到 ListBox 中。列表内容填充在 BackgroundWorker 中,该 BackgroundWorker 在 ViewModel 的构造函数中启动。完成后,我想将焦点设置到列表中的第一首歌曲。
由于设置此焦点纯粹是一个 View 操作,我希望它位于 XAML 的代码隐藏中。焦点所在与 ViewModel 无关。
我尝试在各种 Window 和 ListBox 事件上执行此操作,但它们要么不触发,要么触发得太早。所以我认为我需要的是 ViewModel 在将歌曲加载到列表中后设置的布尔属性。那时我需要 View 来捕获该属性更改,并调用具有操作 View 逻辑的代码隐藏函数,在这种情况下,将焦点设置在列表中的第一首歌曲上。
但这是我对 WPF 的了解不足的地方。我搜索了一下,听起来 DataTrigger 可以解决问题。但是把它放在哪里,正确的语法是什么,以及如何让它调用我的代码隐藏函数?
还是我忽略了一种更简单的方法。这似乎是一个基本功能——当属性在 ViewModel 中以某种方式更改时,在视图中触发一些代码隐藏操作。
这是代码隐藏函数。一旦在预定时间成功调用它,我就可以详细说明它:
Private Sub FocusSongsList()
' set focus back to the Songs list, selected item (couldn't just set focus to the list, it ran forever and looks like it set focus to every item in turn before releasing the UI)
Dim listBoxItem = CType(LstSongs.ItemContainerGenerator.ContainerFromItem(LstSongs.SelectedItem), ListBoxItem)
If Not listBoxItem Is Nothing Then
listBoxItem.Focus()
End If
End Sub
这是我的列表框:
<ListBox x:Name="LstSongs" ItemsSource="{Binding FilteredSongs}" DisplayMemberPath="Path"
HorizontalAlignment="Stretch"
SelectionMode="Extended" SelectionChanged="LstSongs_SelectionChanged" Loaded="FocusSongsList"/>
我将定义一个新属性,该属性可以从 BackgroundWorker 的 RunWorkerCompleted 部分进行设置。
Private _InitialSongLoadCompleted As Boolean
Public Property InitialSongLoadCompleted() As Boolean
Get
Return _InitialSongLoadCompleted
End Get
Set(ByVal value As Boolean)
_InitialSongLoadCompleted = value
RaisePropertyChanged("InitialSongLoadCompleted")
End Set
End Property
【问题讨论】:
-
这是一次性的事情,还是您在第一次展示后更换过清单?
-
您是否考虑过将自定义事件放在您的视图模型上并在您的视图中订阅它?我通常认为数据触发器是纯粹的 XAML 领域的东西。