Виртуализация стековой панели - видимость виртуализированных элементов
У меня есть сценарий, в котором я использую список для отображения большого списка 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>