XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEEDToolBox

【WinUI】XFE精英危险工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
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;

/// <summary>A map overlay whose header stays in place while its content opens to the right.</summary>
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);}
}