移植WPF軟體到uwp時碰到用作對話框的Window有多種處理選擇。我個人認為最省事的是用ContentDialog模擬Window。 比如你想把上面這個WPF窗體弄到uwp裡面去 1.修改ContentDialog的預設樣式 新建一個模板化控制項RoundCornerContentDialog 讓它 ...
移植WPF軟體到uwp時碰到用作對話框的Window有多種處理選擇。我個人認為最省事的是用ContentDialog模擬Window。
比如你想把上面這個WPF窗體弄到uwp裡面去
1.修改ContentDialog的預設樣式
新建一個模板化控制項RoundCornerContentDialog
讓它繼承ContentDialog。
然後去Windows SDK裡面翻預設樣式(因為vs2015 update 1無法自動提取ContentDialog的預設樣式到Xaml)。
我的電腦上預設樣式在這個文件夾
C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.10586.0\Generic
找到之後打開剛纔新建這個控制項時的Themes\Generic.xaml
把ContentDialog的預設樣式換進去。
由於要移植的對話框是圓角的,而且沒有在底部放置額外的按鈕,ContentDialog的樣式需要修改。我把它改成了這樣:
XAML
<Style TargetType="local:RoundCornerContentDialog" > <Setter Property="Foreground" Value="{ThemeResource SystemControlPageTextBaseHighBrush}" /> <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundChromeMediumLowBrush}" /> <Setter Property="HorizontalAlignment" Value="Center" /> <Setter Property="VerticalAlignment" Value="Top" /> <Setter Property="BorderThickness" Value="3" /> <Setter Property="IsTabStop" Value="False" /> <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundAccentBrush}"/> <Setter Property="MaxHeight" Value="{ThemeResource ContentDialogMaxHeight}" /> <Setter Property="MinHeight" Value="{ThemeResource ContentDialogMinHeight}" /> <Setter Property="MaxWidth" Value="{ThemeResource ContentDialogMaxWidth}" /> <Setter Property="MinWidth" Value="{ThemeResource ContentDialogMinWidth}" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="local:RoundCornerContentDialog"> <Border x:Name="Container"> <Grid x:Name="LayoutRoot"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <Border x:Name="BackgroundElement" FlowDirection="{TemplateBinding FlowDirection}" MaxWidth="{TemplateBinding MaxWidth}" MaxHeight="{TemplateBinding MaxHeight}" MinWidth="{TemplateBinding MinWidth}" MinHeight="{TemplateBinding MinHeight}" > <Grid x:Name="DialogSpace" VerticalAlignment="Stretch"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <ScrollViewer x:Name="ContentScrollViewer" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Disabled" ZoomMode="Disabled" IsTabStop="False"> <Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <ContentControl x:Name="Title" Margin="{ThemeResource ContentDialogTitleMargin}" Content="{TemplateBinding Title}" ContentTemplate="{TemplateBinding TitleTemplate}" FontSize="20" FontFamily="XamlAutoFontFamily" FontWeight="Normal" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="Left" VerticalAlignment="Top" IsTabStop="False" MaxHeight="{ThemeResource ContentDialogTitleMaxHeight}" > <ContentControl.Template> <ControlTemplate TargetType="ContentControl"> <ContentPresenter Content="{TemplateBinding Content}" MaxLines="2" TextWrapping="Wrap" ContentTemplate="{TemplateBinding ContentTemplate}" Margin="{TemplateBinding Padding}" ContentTransitions="{TemplateBinding ContentTransitions}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" /> </ControlTemplate> </ContentControl.Template> </ContentControl> <ContentPresenter x:Name="Content" Background="{TemplateBinding Background}" BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{ThemeResource ContentDialogBorderThemeBrush}" CornerRadius="20" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" VerticalContentAlignment="Stretch" FontSize="{ThemeResource ControlContentThemeFontSize}" FontFamily="{ThemeResource ContentControlThemeFontFamily}" Foreground="{TemplateBinding Foreground}" Grid.Row="1" TextWrapping="Wrap" /> </Grid> </ScrollViewer> <Grid x:Name="CommandSpace" Visibility="Collapsed" Grid.Row="1" HorizontalAlignment="Stretch" VerticalAlignment="Bottom"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Border x:Name="Button1Host" Margin="{ThemeResource ContentDialogButton1HostMargin}" MinWidth="{ThemeResource ContentDialogButtonMinWidth}" MaxWidth="{ThemeResource ContentDialogButtonMaxWidth}" Height="{ThemeResource ContentDialogButtonHeight}" HorizontalAlignment="Stretch" /> <Border x:Name="Button2Host" Margin="{ThemeResource ContentDialogButton2HostMargin}" MinWidth="{ThemeResource ContentDialogButtonMinWidth}" MaxWidth="{ThemeResource ContentDialogButtonMaxWidth}" Height="{ThemeResource ContentDialogButtonHeight}" Grid.Column="1" HorizontalAlignment="Stretch" /> </Grid> </Grid> </Border> </Grid> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
2.添加DragMove方法
需要移植的那個WPF視窗是可以在空白處進行拖動的。
通過輸入指針的事件收集信息,對ContentDialog的Margin屬性進行更改達到模擬拖動的效果。
子類調用DragMove方法啟用拖動。
下麵是VB代碼示例。需要其它語言示例的話可以用SharpDevelop轉換。
VB
Protected Sub DragMove(ptr As Pointer) Pressed = True CapturePointer(ptr) End Sub Dim Pressed As Boolean Dim pos As Point Private Sub RoundCornerContentDialog_PointerMoved(sender As Object, e As PointerRoutedEventArgs) Handles Me.PointerMoved If Pressed Then Dim pt = e.GetCurrentPoint(Me).Position Dim marg = Margin Dim ofsx = pt.X - pos.X Dim ofsy = pt.Y - pos.Y marg.Left += ofsx marg.Right -= ofsx marg.Top += ofsy marg.Bottom -= ofsy Margin = marg End If End Sub Private Sub RoundCornerContentDialog_PointerReleased(sender As Object, e As PointerRoutedEventArgs) Handles Me.PointerReleased Pressed = False ReleasePointerCapture(e.Pointer) End Sub Private Sub RoundCornerContentDialog_PointerPressed(sender As Object, e As PointerRoutedEventArgs) Handles Me.PointerPressed pos = e.GetCurrentPoint(Me).Position End Sub
3.把對話框內容加進去
新建一個ContentDialog,並把Xaml根節點的名稱改為剛纔建立的local:RoundCornerContentDialog,還要在相應的類裡面把基類也改成RoundCornerContentDialog。
註意,加入內容時要考慮照顧小屏幕設備和低性能設備。
我把佈局改了一下,按鈕的視覺效果也去除了。
4.在合適的位置調用DragMove
在你認為表示非客戶區中可拖動部分的控制項的PointerPressed調用DragMove
VB
Private Sub RectDrag_PointerPressed(sender As Object, e As PointerRoutedEventArgs) Handles RectDrag.PointerPressed DragMove(e.Pointer) End Sub
5.其它功能的模擬
有些對話框需要拖動改變大小之類複雜的功能。這個可以仿照WPF的自定義處理非客戶區碰撞檢測消息進行編寫。
以後我遇到需要實現這個功能的時候會補上這裡的代碼。