I defined styles for a ListBox to display items with vertical or horizontal scrolling orientation:
<Style x:Key="ListBoxVerticalStyle" TargetType="ListBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Disabled"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ListBoxHorizontalStyle" TargetType="ListBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled"/>
<Setter Property="BorderThickness" Value="0"/>
<Setter Property="BorderBrush" Value="Transparent"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
They are working fine when used statically in xaml, e.g.
<ListBox Style="{StaticResource ListBoxHorizontalStyle}" ...
I am trying to update the orientation dynamically in C# with this code:
if (horizontal)
{
MyListBox.Style = Resources["ListBoxHorizontalStyle"] as Style;
}
else
{
MyListBox.Style = Resources["ListBoxVerticalStyle"] as Style;
}
MyListBox.InvalidateMeasure();
MyListBox.InvalidateArrange();
The ListBox.ScrollViewer
orientation does change, however the items remain stacked in their original orientation. It's as though the ItemsPanel
update doesn't get applied. Is there something I need to do to force the ListBox to completely refresh itself?
I don't think it's raising the PropertyChange event when you do it that way. Top of my head, I only have two solutions. One is derived your own custom ListBox and VisualStates, which is far to long to put as a solution here. The other option is pretty easy, we just need to notify that the property has changed and the easiest way I know how to do that is just bind it your ViewModel.
For this, I just going to use the Page as the ViewModel, so your XAML is like so
<ListBox x:Name="myListBox">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="{Binding MYO}"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>
C#
using System.ComponentModel; // INotifyPropertyChanged
public partial class MainPage : PhoneApplicationPage, INotifyPropertyChanged
{
// implement the INotify
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (null != handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
// Constructor
public MainPage()
{
InitializeComponent();
}
private System.Windows.Controls.Orientation _myo;
public System.Windows.Controls.Orientation MYO
{
get { return _myo; }
set { _myo = value; NotifyPropertyChanged("MYO"); }
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
myListBox.DataContext = this; // have to set the datacontext to point to the page
MYO = System.Windows.Controls.Orientation.Horizontal; // set it to Horizontal
// MYO = System.Windows.Controls.Orientation.Vertical; // set it to Vertical
}
}