问题
My idea is fairly simple and I've seen it many places. I want to be able to expand and contract a list of items based on a click on a button.
ex
- listitem 1
- listitem 2
- subList item 1
- subList item 2
- listItem 3
simply click Listitem 2 and the sublistitems should disapear. click it again or any other listitem and the sublist item belonging to that listitem should reappear.
here is what I've done so far(Doesn't work)
Channels.Xaml:
<UserControl
x:Class="InternetRadio.RadioChannels"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:InternetRadio"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<StackPanel x:Name="stationList" Orientation="Vertical">
<Button x:Name="HamburgerButton" FontFamily="Segoe MDL2 Assets" Content="" Width="50" Height="50" Background="Transparent" Click="HamburgerButton_click"/>
<TextBlock x:Name="textBox" Text="Internet Radio Stations" Padding="50,0,0,0" Height="20px" />
<ToggleButton x:Name="collapsableBtn" Content="DR Channels" Margin="50,0,0,0" Background="Transparent" Click="collapsableBtn_Click" />
<StackPanel x:Name="RadioChannelsCollapsable" Visibility="Collapsed">
<ItemsControl x:Name="tStack" Grid.Column="1" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding ItemName}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</StackPanel>
Channels.xaml.cs
private void collapsableBtn_Click(object sender, RoutedEventArgs e)
{
if(RadioChannelsCollapsable.Visibility == Visibility.Collapsed)
{
RadioChannelsCollapsable.Visibility = Visibility.Visible;
RadioChannelsCollapsable.Children.ToList().ForEach(vis => vis.Visibility = Visibility.Visible);
}
else
{
RadioChannelsCollapsable.Visibility = Visibility.Collapsed;
RadioChannelsCollapsable.Children.ToList().ForEach(vis => vis.Visibility = Visibility.Collapsed);
}
just to be clear this usercontrol is used like this in a splitView: mainpage.xaml
<SplitView x:Name="radioChannelssplitview" DisplayMode="CompactOverlay" IsPaneOpen="False" CompactPaneLength="50" OpenPaneLength="250">
<SplitView.Pane>
<local:RadioChannels x:Name="myControl" Background="Gray"/>
</SplitView.Pane>
<SplitView.Content>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<TextBlock x:Name="StationTitle" Text="Internet Radio" HorizontalAlignment="Center" VerticalAlignment="Top" Height="20px" />
<TextBlock x:Name="ProgramTitle" Text="Welcome Page" HorizontalAlignment="Center" VerticalAlignment="Top" Height="20px" Margin="130,60,140,560" />
</Grid>
</SplitView.Content>
</SplitView>
}
and I cannot make it work :( the splitview opens and closes easily but the stackpanel does not expand and contract at all. please give me a pointer to where or why I'm wrong and/or a pointer to how I should be doing this. Thanks in advance
回答1:
I would rather try to create my own UserControl that can be expaned or not depending on it's VisualState. My quick and simple sample:
MainPage.xaml:
<Page.Resources>
<DataTemplate x:Key="MyItemTemplate">
<local:MyItem></local:MyItem>
</DataTemplate>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ListView ItemsSource="{Binding Items}" ItemTemplate="{StaticResource MyItemTemplate}"
SelectionMode="None" IsItemClickEnabled="True">
</ListView>
</Grid>
MainPage.xamls.cs:
public sealed partial class MainPage : Page
{
public MainPage()
{
InitializeComponent();
DataContext = new ViewModel();
}
}
ViewModel.cs:
public class ViewModel
{
public ViewModel()
{
Items.Add(new MyItemViewModel("Item1"));
Items.Add(new MyItemViewModel("Item2"));
Items.Add(new MyItemViewModel("Item3"));
}
public ApplicationDataLocality ApplicationDataLocalityEnum { get; } =
ApplicationDataLocality.Local;
public FontStyle FontStyleEnum { get; } =
FontStyle.Normal;
public ObservableCollection<MyItemViewModel> Items { get; set; } = new ObservableCollection<MyItemViewModel>();
}
MyItem.xaml.cs:
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Title}" x:Name="TitleBlock" Tapped="Title_OnTapped"/>
<ListView ItemsSource="{Binding Items}" x:Name="ItemsBlock" ItemClick="Items_OnItemClick" IsItemClickEnabled="True"/>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Regular">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemsBlock" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Expanded">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemsBlock" Storyboard.TargetProperty="Visibility" >
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</StackPanel>
MyItem.xaml.cs:
public enum MyItemState
{
Regular,
Expanded
}
public sealed partial class MyItem : UserControl
{
private MyItemState _state;
public MyItemState State
{
get { return _state; }
set
{
_state = value;
VisualStateManager.GoToState(this, _state.ToString(), true);
}
}
public MyItem()
{
InitializeComponent();
State = MyItemState.Regular;
}
private void Title_OnTapped(object sender, TappedRoutedEventArgs e)
{
if (State == MyItemState.Regular)
{
State = MyItemState.Expanded;
}
else
{
State = MyItemState.Regular;
}
}
private void Items_OnItemClick(object sender, ItemClickEventArgs e)
{
// action after subitem is clicked
}
}
and MyItemViewModel:
public class MyItemViewModel
{
public ObservableCollection<TextBlock> Items { get; set; } = new ObservableCollection<TextBlock>();
public string Title { get; set; }
public MyItemViewModel(string title)
{
Title = title;
Items.Add(new TextBlock() { Text = "SubItem1" });
Items.Add(new TextBlock() { Text = "SubItem2" });
Items.Add(new TextBlock() { Text = "SubItem3" });
}
}
whenever you click on the MyItem Title it will change it's state - to expand or shrink it's subItems (only TextBoxes just to keep it simple - may by antoher UserControl with any view you want) that in this case I store in another ListView. ToDo: change the styles and animations so the state change may look better and so on.
来源:https://stackoverflow.com/questions/39325340/how-to-make-a-contractable-stackpanel-in-xaml