虚拟化堆栈面板 - 虚拟化项目可见性

时间:2015-01-25 18:33:07

标签: mvvm visibility virtualization itemcontainerstyle itemcontainergenerator

我有一个场景,我使用一个列表框来显示一个大型ViewModel列表,每个ViewModel都有一个可见性属性,该属性根据应用程序逻辑而变化。

我遇到的问题是,当“虚拟化”项目的可见性发生变化时,滚动条不会更新以反映可滚动范围,直到通过手动滚动将项目置于视图中。

这显然是由于虚拟化项目没有评估可见性绑定这一事实,因此不会添加到可滚动范围,但如何在不禁用可视化的情况下解决问题?

注意:我知道我可以使用过滤CollectionView,但使用Visibility属性可以更好地使用我的应用程序逻辑。

下面是一些演示此问题的代码。

    public class ViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public string Name { get; private set; }
    public Visibility Visibility
    {
        get { return m_visibility; }
        set
        {
            m_visibility = value;
            RaisePropertyChanged("Visibility");
        }
    }

    public ViewModel(string name)
    {
        Name = name;
    }

    protected void RaisePropertyChanged(string property)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    }

    Visibility m_visibility = Visibility.Visible;
}

public partial class MainWindow : Window
{
    public List<ViewModel> ViewModels { get; private set; }

    public MainWindow()
    {
        ViewModels = new List<ViewModel>();

        for(int i = 0; i < 100; ++i)
        {
            ViewModels.Add(new ViewModel("item_" + i));
        }

        DataContext = this;
        InitializeComponent();
    }

    void OnHideItemsClick(object sender, EventArgs e)
    {
        for (int i = 30; i < ViewModels.Count; ++i)
        {
            ViewModels[i].Visibility = Visibility.Collapsed;
        }
    }

    void OnShowItemsClick(object sender, EventArgs e)
    {
        for (int i = 30; i < ViewModels.Count; ++i)
        {
            ViewModels[i].Visibility = Visibility.Visible;
        }
    }
}


<DockPanel>
    <UniformGrid Columns="2" DockPanel.Dock="Top">
        <Button Content="Hide offscreen items" Click="OnHideItemsClick" />
        <Button Content="Show offscreen items" Click="OnShowItemsClick" />
    </UniformGrid>
    <ListBox ItemsSource="{Binding ViewModels}" HorizontalContentAlignment="Stretch">
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Visibility" Value="{Binding Visibility}" />
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Border Margin="1" BorderThickness="1" BorderBrush="Green">
                    <TextBlock Text="{Binding Name}" Margin="5" />
                </Border>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</DockPanel>

0 个答案:

没有答案