简体   繁体   中英

Dynamically change ListBox orientation with Style

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, eg

<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
    }
}

Check this link: http://msdn.microsoft.com/en-us/library/windows/apps/jj207002(v=vs.105).aspx

That tutorial explains how to handle screen orientation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM