2013-04-27 72 views
1

我試圖達到相同的動畫比VS2012設置窗口,autosizing和集中在一個很好的動畫方式每個內容大小的變化。VS2012設置像WPF窗口動畫SizeToContent

問題是,它不能完全由代碼完成,因爲我不知道最終的窗口大小(因爲我依賴SizeToContent =「WidthAndHeight」),但通過它自己讓SizeToContent =「WidthAndHeight」不允許我動畫過渡

有沒有辦法做到這一點?

回答

3

我認爲最簡單的方法是在窗口類中使用自定義視覺狀態。我做了一個小測試項目,你可以在這裏下載:https://dl.dropboxusercontent.com/u/14810011/ResizingWindow.zip

你需要Visual Studio 2012來執行它。

主窗口XAML看起來是這樣的:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:ResizingWindow" 
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 
    x:Name="Window" x:Class="ResizingWindow.MainWindow" 
    Title="MainWindow" Width="350" Height="300" WindowStyle="None" ResizeMode="NoResize" WindowStartupLocation="CenterScreen"> 
<Window.DataContext> 
    <local:MainWindowViewModel /> 
</Window.DataContext> 
    <Grid> 
    <VisualStateManager.VisualStateGroups> 
     <VisualStateGroup x:Name="ExtendedStates"> 
      <VisualStateGroup.Transitions> 
       <VisualTransition GeneratedDuration="0:0:0.6"> 
        <VisualTransition.GeneratedEasingFunction> 
         <CubicEase EasingMode="EaseOut"/> 
        </VisualTransition.GeneratedEasingFunction> 
       </VisualTransition> 
      </VisualStateGroup.Transitions> 
      <VisualState x:Name="Normal"> 
       <Storyboard> 
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="TextBlock"> 
         <EasingDoubleKeyFrame KeyTime="0" Value="0"/> 
        </DoubleAnimationUsingKeyFrames> 
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="Window"> 
         <EasingDoubleKeyFrame KeyTime="0" Value="300"/> 
        </DoubleAnimationUsingKeyFrames> 
       </Storyboard> 
      </VisualState> 
      <VisualState x:Name="Extended"> 
       <Storyboard> 
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="Window"> 
         <EasingDoubleKeyFrame KeyTime="0" Value="400"/> 
        </DoubleAnimationUsingKeyFrames> 
        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="TextBlock"> 
         <EasingDoubleKeyFrame KeyTime="0" Value="1"/> 
        </DoubleAnimationUsingKeyFrames> 
       </Storyboard> 
      </VisualState> 
     </VisualStateGroup> 
    </VisualStateManager.VisualStateGroups> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="300"/> 
     <RowDefinition Height="100"/> 
    </Grid.RowDefinitions> 
    <Border Background="#FF6C6C6C"> 
     <Grid> 
      <TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" Text="Hey, I here is some really cool content." VerticalAlignment="Top" FontSize="32" FontFamily="Segoe UI Light" TextAlignment="Center" Margin="0,50,0,0"/> 
      <CheckBox Content="I want to see more" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,0,0,15" IsChecked="{Binding ShowAdditionalContent}"> 
       <i:Interaction.Behaviors> 
        <ei:DataStateBehavior Binding="{Binding ShowAdditionalContent}" Value="False" TrueState="Normal" FalseState="Extended"/> 
       </i:Interaction.Behaviors> 
      </CheckBox> 
      <Button Content="&#xE221;" HorizontalAlignment="Right" VerticalAlignment="Top" FontFamily="Segoe UI Symbol" FontSize="21.333" Style="{DynamicResource ButtonStyle}" Margin="0,5,5,0" Click="CloseMainWindow"/> 
     </Grid> 
    </Border> 
    <Border Grid.Row="1" Background="#FF383838"> 
     <TextBlock x:Name="TextBlock" TextWrapping="Wrap" Text="You can see this, when the check box is activated." FontFamily="Segoe UI Light" FontSize="18.667" TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="Silver"/> 
    </Border> 
    </Grid> 
</Window> 

你必須要注意的方面如下:

  • 主窗口由一個網格,其第二排是默認隱藏的。這是通過將窗口高度設置爲300而網格實際使用400個邏輯單元來實現的。也可以在運行期間動態計算此高度,但對於此簡單示例,這不是必需的。
  • 當「擴展」視覺狀態激活時,第二行變爲可見。這實際上是通過更新相應視圖模型的複選框以及附加的DataStateBehavior(這是Blend SDK的一部分)對其作出響應來完成的。當狀態改變時,這種行爲確保相應的視覺狀態被激活,即當複選框未被選中時爲「正常」,當被選中時爲「擴展」。
  • WindowStyle設置爲None,而ResizeMode設置爲NoResize。這確保窗口周圍不顯示邊框。也可以選擇將AllowTransparency設置爲true,但我不建議這樣做,因爲這有一些嚴重的性能影響。請注意,默認最小化,最大化/恢復和退出按鈕也不會出現在這個工作方式中。

請隨時詢問您是否還有其他問題。

+0

這正是我想要的。謝謝!!! – user1416197 2013-04-29 06:34:48

+0

現在有點複雜了。想象一下,在轉換之前,我不知道最終的(SizeToContent之後的)窗口大小,因爲它取決於加載的數據。 「這是通過將窗口高度設置爲300,而網格實際使用400個邏輯單元來實現的,也可以在運行時動態計算此高度,但對於這個簡單的示例,這不是必需的」我如何在運行時計算這個高度? – user1416197 2013-05-27 19:29:57

+0

解決方法之一是重寫'MainWindow.MeasureOverride'方法。在它中,只需執行下面這行代碼:var size = base.MeasureOverride(availableSize);'和voilà,就可以得到你想要的大小。在這種情況下,我不會推薦使用視覺狀態來創建故事板,而是在代碼中創建它們,然後啓動它們。您可以閱讀有關度量的更多信息,並安排MSDN上的WPF佈局系統的傳遞(http://msdn.microsoft.com/zh-cn/library/ms745058.aspx#LayoutSystem_Measure_Arrange)。 – feO2x 2013-05-29 18:27:01