在 ViewModel 中设置时 ListView SelectedItem 未突出显示
Posted
技术标签:
【中文标题】在 ViewModel 中设置时 ListView SelectedItem 未突出显示【英文标题】:ListView SelectedItem not highlighted when set in ViewModel 【发布时间】:2014-11-11 07:32:43 【问题描述】:我有一个ListView
和一个ItemSource
数据绑定和一个SelectedItem
数据绑定。
每次按下“下一个”或“上一个”按钮时,ListView
都会填充一个新的ItemSource
。
SelectedItem
相应更新,ItemSource
中的项目具有Selected
状态,因此用户来回导航时可以记住它。
在调试时,一切似乎都运行良好。 VM 按预期更新控件,当我使用下一个和上一个按钮导航时,我还可以看到 ListView
具有正确的选定值。
问题是,无论 ListView 有正确的SelectedItem
,ListView
都不会将SelectedItem
可视化为突出显示。
XAML:
<ListView
x:Name="_matchingTvShowsFromOnlineDatabaseListView"
Grid.Row="0"
Grid.Column="0"
Grid.RowSpan="3"
ItemsSource="Binding AvailableMatchingTvShows"
SelectedItem="Binding AcceptedMatchingTvShow, Mode=TwoWay">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="Binding Name"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
ViewModel 中负责重新填充ItemSource
和SelectedItem
的行为:
private void UpdateForCurrentVisibleTvShow()
var selectedTvShow = FoundTvShows[CurrentTvShow];
// Update the available matches
var availableMatchingTvShows = new ObservableCollection<IWebApiTvShow>();
if (AvailableTvShowMatches[selectedTvShow] != null)
foreach (var webApiTvShow in AvailableTvShowMatches[selectedTvShow])
availableMatchingTvShows.Add(webApiTvShow);
AvailableMatchingTvShows = availableMatchingTvShows;
// Update the selected item
AcceptedMatchingTvShow = availableMatchingTvShows.FirstOrDefault(webApiTvShow => webApiTvShow.Accepted);
// Update the progress text
CurrentTvShowInfoText = string.Format(
"TV Show: 0 (1 of 2 TV Shows)",
FoundTvShows[CurrentTvShow],
CurrentTvShow + 1,
FoundTvShows.Count);
// Update the AcceptedMatchingTvShow selection in the listview
OnPropertyChanged("AcceptedMatchingTvShow");
AcceptedMatchingTvShow
的实现:
public IWebApiTvShow AcceptedMatchingTvShow
get
IWebApiTvShow acceptedTvShow = null;
if (FoundTvShows.Count > 0)
var tvShowName = FoundTvShows[CurrentTvShow];
acceptedTvShow = AvailableTvShowMatches[tvShowName].FirstOrDefault(webApiTvShow => webApiTvShow.Accepted);
return acceptedTvShow;
set
if (value != null)
var tvShowName = FoundTvShows[CurrentTvShow];
var currentlyAcceptedTvShow =
AvailableTvShowMatches[tvShowName].FirstOrDefault(webApiTvShow => webApiTvShow.Accepted);
if (currentlyAcceptedTvShow != null)
currentlyAcceptedTvShow.Accepted = false;
value.Accepted = true;
OnPropertyChanged();
我希望有人能指出我正确的方向。为了清楚起见,ListView 具有正确的项目,并且 SelectedItem 设置了正确的项目。
【问题讨论】:
在this.UpdateLayout();
后面的代码中试试,你可以在SelectionChanged event
上调用它。您不会以这种方式更改VM
中的任何内容,因此只有View
会受到影响。 HTH
你在哪里设置AcceptedMatchingTvShow
?
@Sinatr 我也用那部分代码更新了问题。它没有需要更新的支持字段,它只需要再次读取属性并评估哪个电视节目是Selected
one
你的 OnPropertyChanged();不应该取更改的属性的名称吗?
@sexta13,那个OnPropertyChanged
方法可能在输入参数上声明了CallerMemberNameAttribute
,所以它可以自动访问名称而无需传递它。
【参考方案1】:
嗯,经过大量调试和挖掘,我找到了问题的“解决方案”。我真的很想了解这是否是 WPF 意味着控件的行为方式,或者这是否是 ListView
s 数据绑定部分中的错误。如果有人能告诉我,我对正确答案非常好奇(也许我以错误的方式解决了这个问题,有人可以解释我应该如何做到这一点)。
无论如何,当我创建对象的副本时,问题似乎得到了解决:
public IWebApiTvShow AcceptedMatchingTvShow
get
IWebApiTvShow acceptedTvShow = null;
if (FoundTvShows.Count > CurrentTvShow)
var tvShowName = FoundTvShows[CurrentTvShow];
acceptedTvShow = AvailableTvShowMatches[tvShowName].FirstOrDefault(webApiTvShow => webApiTvShow.Accepted);
if (acceptedTvShow != null)
// I MUST create a new instance of the original object for the ListView to update the selected item (why??)
return new WebApiTvShow(acceptedTvShow);
return null;
set
if (value != null)
var tvShowName = FoundTvShows[CurrentTvShow];
var availableTvShowMatch = AvailableTvShowMatches[tvShowName];
var currentlyAcceptedTvShow = availableTvShowMatch.FirstOrDefault(webApiTvShow => webApiTvShow.Accepted);
if (currentlyAcceptedTvShow != null)
currentlyAcceptedTvShow.Accepted = false;
value.Accepted = true;
OnPropertyChanged();
注意对复制构造函数的调用:
return new WebApiTvShow(acceptedTvShow);
它有效,但对我来说似乎真的很荒谬,并且闻起来像 ListView
中的错误。是吗?
我试图在一个更简单的例子here 中解释同样的问题,如果有人可以确认这个错误或者可以解释我应该如何实现它,我将非常感谢你的见解。
【讨论】:
【参考方案2】:游戏有点晚了,但我一直在用类似的设置跳过箍来解决这个问题。使用 Viewmodel 中的绑定属性或使用绑定 SelectedIndex 的类似属性在 ListView 中设置 SelectedItem 是行不通的。直到我尝试异步执行:
Task.Factory.StartNew(() =>
BoundSelectedIndex = index;
);
似乎有效 - 更高级的贡献者可能会回答为什么...
【讨论】:
以上是关于在 ViewModel 中设置时 ListView SelectedItem 未突出显示的主要内容,如果未能解决你的问题,请参考以下文章
在 UINavigationController 中设置时图像不显示
WPF CommandParameter 在上下文菜单中设置时未更新