using Microsoft.UI.Xaml.Automation; using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Media.Animation; using Microsoft.UI.Xaml.Media; namespace XFEEDToolBox.Controls; /// A map overlay whose header stays in place while its content opens to the right. public sealed class HorizontalPanel:UserControl { public static readonly DependencyProperty HeaderProperty=DependencyProperty.Register(nameof(Header),typeof(string),typeof(HorizontalPanel),new PropertyMetadata("",Changed)); public static readonly DependencyProperty IsExpandedProperty=DependencyProperty.Register(nameof(IsExpanded),typeof(bool),typeof(HorizontalPanel),new PropertyMetadata(true,Changed)); public static readonly DependencyProperty PanelContentProperty=DependencyProperty.Register(nameof(PanelContent),typeof(object),typeof(HorizontalPanel),new PropertyMetadata(null,Changed)); public static readonly DependencyProperty ContentWidthLimitProperty=DependencyProperty.Register(nameof(ContentWidthLimit),typeof(double),typeof(HorizontalPanel),new PropertyMetadata(900d,Changed)); public string Header {get=>(string)GetValue(HeaderProperty);set=>SetValue(HeaderProperty,value);} public bool IsExpanded {get=>(bool)GetValue(IsExpandedProperty);set=>SetValue(IsExpandedProperty,value);} public object? PanelContent {get=>GetValue(PanelContentProperty);set=>SetValue(PanelContentProperty,value);} public double ContentWidthLimit {get=>(double)GetValue(ContentWidthLimitProperty);set=>SetValue(ContentWidthLimitProperty,value);} private readonly ToggleButton toggle=new(){Width=136,MinHeight=48,VerticalAlignment=VerticalAlignment.Top,Margin=new(8),HorizontalContentAlignment=HorizontalAlignment.Stretch}; private readonly TextBlock title=new(){TextWrapping=TextWrapping.Wrap,VerticalAlignment=VerticalAlignment.Center}; private readonly FontIcon chevron=new(){FontSize=12,VerticalAlignment=VerticalAlignment.Center}; private readonly ContentPresenter presenter=new(){VerticalAlignment=VerticalAlignment.Top}; private readonly Border body=new(){VerticalAlignment=VerticalAlignment.Top}; private readonly ScrollViewer scroll=new(){HorizontalScrollBarVisibility=ScrollBarVisibility.Auto,VerticalScrollBarVisibility=ScrollBarVisibility.Disabled,HorizontalContentAlignment=HorizontalAlignment.Left,VerticalContentAlignment=VerticalAlignment.Top,VerticalAlignment=VerticalAlignment.Top}; private readonly Button back=new(){Content="← 返回上一级",Margin=new(8,0,8,8),FontSize=11,Visibility=Visibility.Collapsed}; public HorizontalPanel() { var header=new Grid{ColumnSpacing=8};header.ColumnDefinitions.Add(new(){Width=new(1,GridUnitType.Star)});header.ColumnDefinitions.Add(new(){Width=GridLength.Auto}); header.Children.Add(title);Grid.SetColumn(chevron,1);header.Children.Add(chevron);toggle.Content=header; VerticalContentAlignment=VerticalAlignment.Top; var root=new Grid{ColumnSpacing=12,VerticalAlignment=VerticalAlignment.Top};root.ColumnDefinitions.Add(new(){Width=GridLength.Auto});root.ColumnDefinitions.Add(new(){Width=GridLength.Auto}); root.RowDefinitions.Add(new(){Height=GridLength.Auto}); body.Child=presenter;body.Transitions=[new EntranceThemeTransition{FromHorizontalOffset=24,FromVerticalOffset=0}]; foreach(var state in new[]{"Checked","CheckedPointerOver","CheckedPressed"}) { toggle.Resources["ToggleButtonBackground"+state]=new SolidColorBrush(Windows.UI.Color.FromArgb(state=="Checked"?(byte)0:(byte)32,17,29,43)); toggle.Resources["ToggleButtonForeground"+state]=Application.Current.Resources["MainTextBrush"]; } var rail=new StackPanel{VerticalAlignment=VerticalAlignment.Top};rail.Children.Add(toggle);rail.Children.Add(back); var headerPane=new Border{Style=(Style)Application.Current.Resources["MapOverlayStyle"],Padding=new(0),VerticalAlignment=VerticalAlignment.Top,Child=rail}; scroll.Content=body;root.Children.Add(headerPane);Grid.SetColumn(scroll,1);root.Children.Add(scroll);Content=root; scroll.ViewChanged+=(_,_)=>back.Visibility=IsExpanded&&scroll.HorizontalOffset>1?Visibility.Visible:Visibility.Collapsed; back.Click+=(_,_)=>scroll.ChangeView(Math.Max(0,scroll.HorizontalOffset-242),null,null); toggle.Checked+=(_,_)=>IsExpanded=true;toggle.Unchecked+=(_,_)=>IsExpanded=false;Update(); } private static void Changed(DependencyObject sender,DependencyPropertyChangedEventArgs e)=>((HorizontalPanel)sender).Update(); private void Update() { title.Text=Header;toggle.IsChecked=IsExpanded;chevron.Glyph=IsExpanded?"\uE76B":"\uE76C"; presenter.Content=PanelContent;scroll.MaxWidth=Math.Max(128,ContentWidthLimit);scroll.Visibility=IsExpanded?Visibility.Visible:Visibility.Collapsed; back.Visibility=IsExpanded&&scroll.HorizontalOffset>1?Visibility.Visible:Visibility.Collapsed; var hint=(IsExpanded?"向左收起":"向右展开")+Header+"面板";AutomationProperties.SetName(toggle,hint);ToolTipService.SetToolTip(toggle,hint); } public void RevealRight(){UpdateLayout();scroll.ChangeView(scroll.ScrollableWidth,null,null);} }