1. 程式人生 > 其它 >WPF實現新手引導

WPF實現新手引導

1. 半透明灰的遮罩層

  • 新建一個遮蓋的window窗體
  • canvas是後期可以在思顯示高亮區域
//定義一個window將它的樣式設定透明等可以覆蓋到其他窗體上,其中遮罩層使用border控制元件
//原因
//1. 支援圓角和方向可以適應不同的窗體樣式 2. 支援陰影效果
<Grid Background="#01000000" MouseLeftButtonDown="Grid_MouseLeftButtonDown">
        <Border x:Name="border">
            <Border Margin="0"
                    Background="#000000"
                    Opacity="0.5" />
        </Border>
        <Canvas x:Name="canvas" />
    </Grid>

2. 汽包的設定

  • 建一個"自定義控制元件(UserControl)"設定自定義汽包樣式
  • 規劃好樣式設定
點選檢視程式碼
 <Grid>
        <Grid.RowDefinitions>
            <RowDefinition x:Name="row1" />
            <RowDefinition x:Name="row2" Height="auto" />
            <RowDefinition x:Name="row3" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="colum1" />
            <ColumnDefinition x:Name="colum2" Width="auto" />
            <ColumnDefinition x:Name="colum3" />
        </Grid.ColumnDefinitions>
        <StackPanel Grid.Row="1"
                    HorizontalAlignment="Right"
                    VerticalAlignment="Center"
                    Orientation="Horizontal">
            <Grid>
                <Ellipse Width="20"
                         Height="20"
                         Fill="White"
                         Opacity="0.5" />
                <Ellipse Width="10"
                         Height="10"
                         HorizontalAlignment="Center"
                         Fill="White" />
            </Grid>
            <Line Height="2"
                  VerticalAlignment="Center"
                  Stroke="White"
                  StrokeDashArray="2,1"
                  StrokeThickness="2"
                  X1="0"
                  X2="30"
                  Y1="0"
                  Y2="0" />
            <Path Height="12"
                  VerticalAlignment="Center"
                  Data="M 10,0 0,6 10,12 Z"
                  Fill="White" />
        </StackPanel>
        <StackPanel Grid.Column="1"
                    VerticalAlignment="Bottom"
                    Orientation="Vertical">
            <Grid>
                <Ellipse Width="20"
                         Height="20"
                         Fill="White"
                         Opacity="0.5" />
                <Ellipse Width="10"
                         Height="10"
                         HorizontalAlignment="Center"
                         Fill="White" />
            </Grid>
            <Line Width="2"
                  HorizontalAlignment="Center"
                  Stroke="White"
                  StrokeDashArray="2,1"
                  StrokeThickness="2"
                  X1="2"
                  X2="2"
                  Y1="0"
                  Y2="30" />
            <Path HorizontalAlignment="Center"
                  Data="M 0,10 6,0 12,10 Z"
                  Fill="White" />
        </StackPanel>
        <StackPanel Grid.Row="1"
                    Grid.Column="2"
                    HorizontalAlignment="Left"
                    VerticalAlignment="Center"
                    Orientation="Horizontal">
            <Path Height="12"
                  VerticalAlignment="Center"
                  Data="M 0,0 10,6 0,12 Z"
                  Fill="White" />
            <Line Height="1"
                  VerticalAlignment="Center"
                  Stroke="White"
                  StrokeDashArray="2,1"
                  StrokeThickness="2"
                  X1="0"
                  X2="30"
                  Y1="0"
                  Y2="0" />
            <Grid>
                <Ellipse Width="20"
                         Height="20"
                         Fill="White"
                         Opacity="0.5" />
                <Ellipse Width="10"
                         Height="10"
                         HorizontalAlignment="Center"
                         Fill="White" />
            </Grid>
        </StackPanel>
        <StackPanel Grid.Row="2"
                    Grid.Column="1"
                    VerticalAlignment="Top"
                    Orientation="Vertical">
            <Path HorizontalAlignment="Center"
                  Data="M 0,0 6,10 12,0 Z"
                  Fill="White" />
            <Line Width="2"
                  HorizontalAlignment="Center"
                  Stroke="White"
                  StrokeDashArray="2,1"
                  StrokeThickness="2"
                  X1="2"
                  X2="2"
                  Y1="0"
                  Y2="30" />
            <Grid>
                <Ellipse Width="20"
                         Height="20"
                         Fill="White"
                         Opacity="0.5" />
                <Ellipse Width="10"
                         Height="10"
                         HorizontalAlignment="Center"
                         Fill="White" />
            </Grid>
        </StackPanel>
        <Border Grid.Row="1"
                Grid.Column="1"
                Padding="10"
                Background="White"
                CornerRadius="5">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="auto" />
                    <RowDefinition Height="40" />
                </Grid.RowDefinitions>
                <TextBlock x:Name="txtNum"
                           HorizontalAlignment="Left"
                           FontSize="12"
                           FontWeight="Regular"
                           Foreground="#666666 ">
                    <Run Text="1" />
                    <Run Text="/" />
                    <Run Text="3" />
                </TextBlock>
                <aps:ImageButton Margin="-13,-3,-15,0"
                                 HorizontalAlignment="Right"
                                 VerticalAlignment="Top"
                                 Background="White"
                                 Click="Close_Click"
                                 HoverImage="/Resources/Images/Close_Hover.svg"
                                 ImageHeight="9"
                                 ImageWidth="9"
                                 NormalImage="/Resources/Images/Close.svg"
                                 PressedImage="/Resources/Images/Close_Pressed.svg" />
                <TextBox Grid.Row="1"
                         MaxWidth="190"
                         Margin="10"
                         HorizontalAlignment="Center"
                         VerticalAlignment="Center"
                         Background="Transparent"
                         BorderThickness="0"
                         Cursor="Arrow"
                         FontSize="14"
                         FontWeight="Regular"
                         Foreground="#333333 "
                         IsReadOnly="True"
                         Text="提示的語句"
                         TextWrapping="Wrap" />
                <Button Grid.Row="2"
                        Height="30"
                        MinWidth="100"
                        Padding="10,5"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        Click="Next_Click"
                        Content="按鈕的內容"
                        FontSize="12"
                        Foreground="#FFFFFF " />
            </Grid>
        </Border>
    </Grid>

3. 汽包出現的位置

  • 通過TransformToAncestor方法拿到控制元件座標之後從左上角(0,0)點的位置在帶入控制元件的寬高計算出起點的座標
    點選檢視程式碼
    //汽包應該顯示在那個位置
    public void StartGuide(GuideModel guide) {
                //這個是拿到自定義控制元件
                var focusElemt = guide.UserControl;
                var window = Window.GetWindow(focusElemt);
                var point = focusElemt.TransformToAncestor(window).Transform(new Point(0, 0));
                var rectangleGeometry = new RectangleGeometry();
                rectangleGeometry.Rect = new Rect(0, 0, this.Width, this.Height);
                borderGeometry = Geometry.Combine(borderGeometry, rectangleGeometry, GeometryCombineMode.Union, null);
                var rectangleGeometry1 = new RectangleGeometry();
                //自適應一下
                rectangleGeometry1.Rect = new Rect(point.X - 5, point.Y - 5, focusElemt.ActualWidth + 10, focusElemt.ActualHeight + 10);
                rectangleGeometry1.RadiusX = 5;
                rectangleGeometry1.RadiusY = 5;
                borderGeometry = Geometry.Combine(borderGeometry, rectangleGeometry1, GeometryCombineMode.Exclude, null);
                border.Clip = borderGeometry;
                //將初始化完的汽包傳進來
                InitHintControl(guide, point);
                //實現步驟的一個累加
                currentStep++;
            }

    初始化汽包

new一個新的物件傳入自定義控制元件“Steptip”以及傳入對應的引數

 private async void InitHintControl(GuideModel guideModel, Point point) {
            //傳入對應的引數
            stepTip = new StepTip(guideModel.ArrowDirection, guideModel.TipText, guideModel.ButtonContent, guideModel.Step, guideModel.TotalStep);
            //這個是解決“步驟引導”每個都從左上角(0,0)開始尋找 這個是讓它尋找完後再顯示出來
            stepTip.Visibility = Visibility.Hidden;
            stepTip.OnNext += StepTip_OnNext;
            stepTip.OnClosed += StepTip_OnClosed;
            canvas.Children.Add(stepTip);
            //防止未生成
            await Task.Delay(50);
            //對自定義控制元件每個方向的確定 尋找以及位置的顯示的高亮區域
            switch (guideModel.ArrowDirection) {
                case StepTip.Direction.Top:
                    Canvas.SetLeft(stepTip, point.X + 5 - ((stepTip.ActualWidth - guideModel.UserControl.ActualWidth) / 2));
                    Canvas.SetTop(stepTip, point.Y + 5 + guideModel.UserControl.ActualHeight);
                    break;
                case StepTip.Direction.Bottom:
                    Canvas.SetLeft(stepTip, point.X + ((guideModel.UserControl.ActualWidth - stepTip.ActualWidth) / 2));
                    Canvas.SetBottom(stepTip, this.ActualHeight - point.Y + 5);
                    break;
                case StepTip.Direction.Left:
                    Canvas.SetLeft(stepTip, point.X + 5 + guideModel.UserControl.ActualWidth);
                    Canvas.SetTop(stepTip, point.Y + 5 + ((guideModel.UserControl.ActualHeight - stepTip.ActualHeight) / 2));
                    break;
                case StepTip.Direction.Right:
                    Canvas.SetLeft(stepTip, point.X-5 - stepTip.ActualWidth);
                    Canvas.SetTop(stepTip, point.Y + 5 + ((guideModel.UserControl.ActualHeight - stepTip.ActualHeight) / 2));
                    break;
                default:
                    break;
            }
            stepTip.Visibility = Visibility.Visible;
        }

步驟的下一步進行與關閉操作

點選檢視程式碼
 private void StepTip_OnClosed() {
            this.Close();
            MainWindow.Instance.Activate();
        }

        private void StepTip_OnNext() {
            if (guideWindows.Count == 0)
                return;
            var beforGuide = guideWindows[currentStep - 1];

            if (guideWindows.Count == currentStep) {
                EndStep();
                return;
            }

            var currentGuide = guideWindows[currentStep];
            if (beforGuide != null) {
                canvas.Children.Clear();
            }

            if (currentGuide != null) {
                StartGuide(currentGuide);
            }
        }

實行如何找到要提示的內容

  • 在要執行的頁面建一個“Loaded”事件
  • 初始化InitGuideWindow();
  • 點選檢視程式碼
     private void EditPage_Loaded(object sender, RoutedEventArgs e) {
                InitGuideWindow();
            }
            private void InitGuideWindow() {
                    var allGuide = new List<GuideModel>();
                    allGuide.AddRange(InitWelecome());
                    var akkGuides = allGuide.OrderBy(i => i.Step).ToList();
                    guideWindow = new GuideWindow(MainWindow.Instance, akkGuides);
                    guideWindow.Owner = MainWindow.Instance;
                    guideWindow.ShowDialog();
                }
            }
    //尋找控制元件
     List<GuideModel> InitWelecome() {
                var lstWelecome = new List<GuideModel>();
                var findCtrl = ControlHelper.FindControl<StackPanel>("optionPanel", optionGrid);
                var createModel = new GuideModel() {
                    Step = 1,
                    TipText = LangEx.Get("MoreFeatures"),
                    UserControl = findCtrl,
                    ArrowDirection = Controls.StepTip.Direction.Left,
                    TotalStep = 3,
                    ButtonContent = LangEx.Get("Know")
                };
                lstWelecome.Add(createModel);
    
                var findCtrl1 = ControlHelper.FindControl<Button>("btnSave", panelWorkspace);
                var createModel1 = new GuideModel() {
                    Step = 3,
                    TipText = LangEx.Get("SaveMattingResults"),
                    UserControl = findCtrl1,
                    ArrowDirection = Controls.StepTip.Direction.Bottom,
                    TotalStep = 3,
                    ButtonContent = LangEx.Get("Know")
                };
                lstWelecome.Add(createModel1);
                var findCtrl2 = ControlHelper.FindControl<Button>("btnSetting", MainWindow.Instance);
                findCtrl2.Margin = new Thickness(10, 0,10, 0);
                var createModel2 = new GuideModel() {
                    Step = 2,
                    TipText = LangEx.Get("PromptStorageLocation"),
                    UserControl = findCtrl2,
                    ArrowDirection = Controls.StepTip.Direction.Top,
                    TotalStep = 3,
                    ButtonContent = LangEx.Get("Know")
                };
                lstWelecome.Add(createModel2);
                return lstWelecome;
            }