WPF實現新手引導
阿新 • • 發佈:2021-09-29
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; }