如何在 Xaml 中制作可收缩的堆栈面板
how to make a contractable stackpanel in Xaml
我的想法很简单,我在很多地方都见过。
我希望能够通过单击按钮来扩展和收缩项目列表。
前
- 列表项 1
- 列表项 2
- 子列表项 1
- 子列表项 2
- 列表项 3
只需单击列表项 2,子列表项就会消失。再次单击它或任何其他列表项,属于该列表项的子列表项应重新出现。
这是我到目前为止所做的(不起作用)
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);
}
需要说明的是,这个用户控件在 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>
}
我无法让它工作 :( splitview 可以轻松打开和关闭,但 stackpanel 根本不会扩展和收缩。请指出我错在哪里或为什么错了 and/or 一个指针我应该怎么做。提前致谢
我宁愿尝试创建自己的 UserControl,它可以扩展或不扩展,具体取决于它的 VisualState。我的快速简单示例:
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
}
}
和 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" });
}
}
每当您单击 MyItem 标题时,它都会更改它的状态 - 扩展或缩小它的子项(只有 TextBoxes 只是为了保持简单 - 可以由 antoher UserControl 以任何你想要的视图),在这种情况下我存储在另一个列表视图。
ToDo:改变样式和动画,使状态变化看起来更好等等。
我的想法很简单,我在很多地方都见过。 我希望能够通过单击按钮来扩展和收缩项目列表。
前
- 列表项 1
- 列表项 2
- 子列表项 1
- 子列表项 2
- 列表项 3
只需单击列表项 2,子列表项就会消失。再次单击它或任何其他列表项,属于该列表项的子列表项应重新出现。
这是我到目前为止所做的(不起作用)
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);
}
需要说明的是,这个用户控件在 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>
}
我无法让它工作 :( splitview 可以轻松打开和关闭,但 stackpanel 根本不会扩展和收缩。请指出我错在哪里或为什么错了 and/or 一个指针我应该怎么做。提前致谢
我宁愿尝试创建自己的 UserControl,它可以扩展或不扩展,具体取决于它的 VisualState。我的快速简单示例:
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
}
}
和 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" });
}
}
每当您单击 MyItem 标题时,它都会更改它的状态 - 扩展或缩小它的子项(只有 TextBoxes 只是为了保持简单 - 可以由 antoher UserControl 以任何你想要的视图),在这种情况下我存储在另一个列表视图。 ToDo:改变样式和动画,使状态变化看起来更好等等。