在ViewModel中设置时,ListView SelectedItem不会突出显示

时间:2014-09-17 10:02:14

标签: c# wpf listview highlighting selecteditem

我有ListView ItemSource数据绑定和SelectedItem数据绑定。

每次按下“下一个”或“上一个”按钮时,ListView都会填充新的ItemSource

SelectedItem相应地更新,ItemSource中的项目具有Selected状态,因此当用户来回导航时可以记住它。

调试时,一切似乎都很完美。 VM按预期更新控件,当我使用下一个和上一个按钮导航时,我还可以看到ListView具有正确的选定值。

问题是,无论ListView具有正确的SelectedItemListView都不会将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中的行为负责重新填充ItemSourceSelectedItem

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设置了正确的项目。

2 个答案:

答案 0 :(得分:0)

好吧,我发现了一个解决方案&#39;经过大量的调试和挖掘后才能解决问题。我真的很想知道这是WPF意味着控件的行为,或者这是ListView数据绑定部分中的错误。如果有人能告诉我,我对正确的答案非常好奇(也许我以错误的方式解决了这个问题,有人可以解释我应该如何做到这一点)。

无论如何,当我创建对象的副本时,问题似乎得到了解决:

    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中解释相同的问题,如果有人可以确认错误或者可以解释我应该如何实现这一点我会非常感谢这些见解。

答案 1 :(得分:0)

游戏开始有点晚,但是我一直在跳铁圈以类似的方式解决这个问题。使用Viewmodel中的绑定属性在ListView中设置SelectedItem或使用绑定的SelectedIndex设置类似项将不起作用。直到我尝试使其异步:

Task.Factory.StartNew(() =>
   {
       BoundSelectedIndex = index;
   });

似乎可以正常工作-更高级的贡献者可能会回答原因...