Виртуализация стековой панели - видимость виртуализированных элементов

У меня есть сценарий, в котором я использую список для отображения большого списка ViewModels, каждый со свойством видимости, которое изменяется в зависимости от логики приложения.

Проблема, с которой я сталкиваюсь, заключается в том, что когда видимость "виртуализированного" элемента изменяется, полоса прокрутки не обновляется, чтобы отображать диапазон прокрутки, пока элементы не будут отображены в результате ручной прокрутки.

Это явно связано с тем фактом, что для виртуализированных элементов не выполняется оценка привязки видимости, и поэтому они не добавляются в прокручиваемый диапазон, но как я могу обойти проблему, не отключая визуализацию?

Примечание: я знаю, что мог бы использовать фильтрацию 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 ответов

Другие вопросы по тегам