metro 里面自定义双面控件,正方面的

先看generic。XAML

View Code
<Style TargetType="local:CustomControl1">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:CustomControl1">
                    <Grid>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="ViewStates">
                                <VisualStateGroup.Transitions>
                                    <VisualTransition GeneratedDuration="0:0:0.7" To="Flipped">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="FlipButtonTransform"
       Storyboard.TargetProperty="Angle" To="90" Duration="0:0:0.2"></DoubleAnimation>
                                        </Storyboard>
                                    </VisualTransition>
                                    <VisualTransition GeneratedDuration="0:0:0.7" To="Normal">
                                        <Storyboard>
                                            <DoubleAnimation Storyboard.TargetName="FlipButtonTransform"
       Storyboard.TargetProperty="Angle" To="-90" Duration="0:0:0.2"></DoubleAnimation>
                                        </Storyboard>
                                    </VisualTransition>
                                </VisualStateGroup.Transitions>

                                <VisualState x:Name="Normal">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="BackContent" 
                       Storyboard.TargetProperty="Opacity" To="0" Duration="0" ></DoubleAnimation>
                                    </Storyboard>
                                </VisualState>

                                <VisualState x:Name="Flipped">
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="FlipButtonTransform"
       Storyboard.TargetProperty="Angle" To="90" Duration="0"></DoubleAnimation>
                                        <DoubleAnimation Storyboard.TargetName="FrontContent" 
                       Storyboard.TargetProperty="Opacity" To="0" Duration="0"></DoubleAnimation>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>

                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                        </Grid.RowDefinitions>

                        <!-- This is the front content. -->
                        <Border x:Name="FrontContent" BorderBrush="{TemplateBinding BorderBrush}"
               BorderThickness="{TemplateBinding BorderThickness}"
               CornerRadius="{TemplateBinding CornerRadius}"
               >
                            <ContentPresenter
                     Content="{TemplateBinding FrontContent}">
                            </ContentPresenter>
                        </Border>

                        <!-- This is the back content. -->
                        <Border x:Name="BackContent" BorderBrush="{TemplateBinding BorderBrush}"
           BorderThickness="{TemplateBinding BorderThickness}"
           CornerRadius="{TemplateBinding CornerRadius}"
           >
                            <ContentPresenter
                     Content="{TemplateBinding BackContent}">
                            </ContentPresenter>
                        </Border>

                        <!-- This the flip button. -->
                        <ToggleButton Grid.Row="1" x:Name="FlipButton" RenderTransformOrigin="0.5,0.5"
                     Margin="0,10,0,0" Width="19" Height="19">
                            <ToggleButton.Template>
                                <ControlTemplate>
                                    <Grid>
                                        <Ellipse Stroke="#FFA9A9A9"  Fill="AliceBlue"  />
                                        <Path Data="M1,1.5L4.5,5 8,1.5"
                             Stroke="#FF666666" StrokeThickness="2"
                             HorizontalAlignment="Center" VerticalAlignment="Center">

                                        </Path>
                                    </Grid>
                                </ControlTemplate>
                            </ToggleButton.Template>

                            <ToggleButton.RenderTransform>

                                <RotateTransform x:Name="FlipButtonTransform" Angle="-90"></RotateTransform>

                            </ToggleButton.RenderTransform>
                        </ToggleButton>



                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

然后是cs 文件

View Code
namespace Tiles
{
    [TemplatePart(Name = "FlipButton", Type = typeof(ToggleButton)),
    TemplatePart(Name = "FlipButtonAlternate", Type = typeof(ToggleButton)),
    TemplateVisualState(Name = "Normal", GroupName = "ViewStates"),
    TemplateVisualState(Name = "Flipped", GroupName = "ViewStates")]
    public sealed class CustomControl1 : Control
    {
        public CustomControl1()
        {
            this.DefaultStyleKey = typeof(CustomControl1);
        }
        static  CustomControl1()
            {
               
    }
        public static readonly DependencyProperty FrontContentProperty = DependencyProperty.Register("FrontContent", typeof(object), typeof(CustomControl1), null);
        public static readonly DependencyProperty BackContentProperty = DependencyProperty.Register("BackContent", typeof(object), typeof(CustomControl1), null);
        public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register("CornerRadius", typeof(CornerRadius), typeof(CustomControl1), null);
        public static readonly DependencyProperty IsFlippedProperty = DependencyProperty.Register("IsFlipped", typeof(bool), typeof(CustomControl1), null);

        public object FrontContent
        {
            get
            {
                return GetValue(FrontContentProperty);
            }
            set
            {
                SetValue(FrontContentProperty, value);
            }
        }

        public object BackContent
        {
            get
            {
                return GetValue(BackContentProperty);
            }
            set
            {
                SetValue(BackContentProperty, value);
            }
        }

        public CornerRadius CornerRadius
        {
            get
            {
                return (CornerRadius)GetValue(CornerRadiusProperty);
            }
            set
            {
                SetValue(CornerRadiusProperty, value);
            }
        }

        public bool IsFlipped
        {
            get
            {
                return (bool)GetValue(IsFlippedProperty);
            }
            set
            {
                SetValue(IsFlippedProperty, value);      

                ChangeVisualState(true);
            }
        }

       

        protected override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            ToggleButton flipButton = base.GetTemplateChild("FlipButton") as ToggleButton;
            if (flipButton != null) flipButton.Click += flipButton_Click;

            // Allow for two flip buttons if needed (one for each side of the panel).
            // This is an optional design, as the control consumer may use template
            // that places the flip button outside of the panel sides, like the 
            // default template does.
            ToggleButton flipButtonAlternate = base.GetTemplateChild("FlipButtonAlternate") as ToggleButton;
            if (flipButtonAlternate != null)
                flipButtonAlternate.Click += flipButton_Click;

            this.ChangeVisualState(false);
        }

        private void flipButton_Click(object sender, RoutedEventArgs e)
        {
            this.IsFlipped = !this.IsFlipped;
        }

        private void ChangeVisualState(bool useTransitions)
        {
            if (!this.IsFlipped)
            {                
                VisualStateManager.GoToState(this, "Normal", useTransitions);
            }
            else
            {
                VisualStateManager.GoToState(this, "Flipped", useTransitions);                
            }

            // Disable flipped side to prevent tabbing to invisible buttons.            
            UIElement front = FrontContent as UIElement;
            if (front != null)
            {
                if (IsFlipped)
                {
                    front.Visibility = Visibility.Collapsed;                    
                }
                else
                {
                    front.Visibility = Visibility.Visible;                    
                }
            }
            UIElement back = BackContent as UIElement;
            if (back != null)
            {
                if (IsFlipped)
                {
                    back.Visibility = Visibility.Visible;                    
                }
                else
                {
                    back.Visibility = Visibility.Collapsed;                    
                }
            }        
        }                            
    }
}


分析一下,注册两个object 类型DependencyProperty,

 public static readonly DependencyProperty FrontContentProperty = DependencyProperty.Register("FrontContent", typeof(object), typeof(CustomControl1), null);

  public object FrontContent
        {
            get
            {
                return GetValue(FrontContentProperty);
            }
            set
            {
                SetValue(FrontContentProperty, value);
            }
        }

重写OnApplyTemplate 这个方法

然后控制VisualState,

   private void ChangeVisualState(bool useTransitions)
        {
            if (!this.IsFlipped)
            {               
                VisualStateManager.GoToState(this, "Normal", useTransitions);
            }
            else
            {
                VisualStateManager.GoToState(this, "Flipped", useTransitions);               
            }

            // Disable flipped side to prevent tabbing to invisible buttons.           
            UIElement front = FrontContent as UIElement;
            if (front != null)
            {
                if (IsFlipped)
                {
                    front.Visibility = Visibility.Collapsed;                   
                }
                else
                {
                    front.Visibility = Visibility.Visible;                   
                }
            }
            UIElement back = BackContent as UIElement;
            if (back != null)
            {
                if (IsFlipped)
                {
                    back.Visibility = Visibility.Visible;                   
                }
                else
                {
                    back.Visibility = Visibility.Collapsed;                   
                }
            }       
        }              

分别设置 backcontent 和frontcontent的可见性

然后是调用这个自定义控件的方法

  <lib:CustomControl1 x:Name="panel" BorderBrush="DarkOrange" BorderThickness="3" IsFlipped="True"
                 Template="{StaticResource AlternateTemplate}"    CornerRadius="4" Margin="10">
                        <lib:CustomControl1.Projection>
                            <PlaneProjection/>
                        </lib:CustomControl1.Projection>
                   
                    
                          
                   
                        <lib:CustomControl1.FrontContent>
                            <StackPanel Margin="6">
                                <TextBlock TextWrapping="Wrap" Margin="3" FontSize="16" Foreground="DarkOrange">This is the front side of the FlipPanel.</TextBlock>
                                <Button Margin="3" Padding="3" Content="Button One"></Button>
                                <Button Margin="3" Padding="3" Content="Button Two"></Button>
                                <Button Margin="3" Padding="3" Content="Button Three"></Button>
                                <Button Margin="3" Padding="3" Content="Button Four"></Button>
                            </StackPanel>
                        </lib:CustomControl1.FrontContent>
                        <lib:CustomControl1.BackContent>
                            <Grid Margin="6">
                                <Grid.RowDefinitions>
                                    <RowDefinition Height="Auto"></RowDefinition>
                                    <RowDefinition></RowDefinition>
                                </Grid.RowDefinitions>
                                <TextBlock TextWrapping="Wrap" Margin="3" FontSize="16" Foreground="DarkMagenta">This is the back side of the FlipPanel.</TextBlock>
                                <Button Grid.Row="2" Margin="3" Padding="10" Content="Flip Back to Front" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click_1"></Button>
                            </Grid>
                        </lib:CustomControl1.BackContent>
                    </lib:CustomControl1>

 

控制正反两面的可见性

    <ControlTemplate x:Key="AlternateTemplate" TargetType="lib:CustomControl1">
            <Grid>
                <VisualStateManager.VisualStateGroups>
                    <VisualStateGroup x:Name="ViewStates">

                        <VisualState x:Name="Normal">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="FrontContentTransform"
                       Storyboard.TargetProperty="ScaleY" To="1" ></DoubleAnimation>

                            

                                <DoubleAnimation Storyboard.TargetName="BackContentTransform"
                       Storyboard.TargetProperty="ScaleY" To="0" ></DoubleAnimation>

                              
                            </Storyboard>
                        </VisualState>

                        <VisualState x:Name="Flipped">
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetName="FrontContentTransform"
                       Storyboard.TargetProperty="ScaleY" To="0" ></DoubleAnimation>

                             

                                <DoubleAnimation Storyboard.TargetName="BackContentTransform"
                       Storyboard.TargetProperty="ScaleY" To="1" ></DoubleAnimation>

                            
                            </Storyboard>
                        </VisualState>
                    </VisualStateGroup>
                </VisualStateManager.VisualStateGroups>

 

                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto"></RowDefinition>
                    <RowDefinition Height="Auto"></RowDefinition>
                </Grid.RowDefinitions>

                <!-- This is the front content. -->
                <Border BorderBrush="{TemplateBinding BorderBrush}"
               BorderThickness="{TemplateBinding BorderThickness}"
               CornerRadius="{TemplateBinding CornerRadius}"
                            Background="{TemplateBinding Background}"
               >
                    <Border.RenderTransform>
                        <ScaleTransform x:Name="FrontContentTransform"></ScaleTransform>
                    </Border.RenderTransform>
                  

                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition></RowDefinition>
                            <RowDefinition Height="Auto"></RowDefinition>
                        </Grid.RowDefinitions>
                        <ContentPresenter
                     Content="{TemplateBinding FrontContent}">
                        </ContentPresenter>

                        <Rectangle Grid.Row="1" Stretch="Fill" Fill="LightSteelBlue"></Rectangle>
                        <ToggleButton Grid.Row="1" x:Name="FlipButton" Margin="5" Padding="15,0"
                             Content="˄" FontWeight="Bold" FontSize="12" HorizontalAlignment="Right">
                        </ToggleButton>
                    </Grid>

                </Border>

                <!-- This is the back content. -->
                <Border BorderBrush="{TemplateBinding BorderBrush}"
           BorderThickness="{TemplateBinding BorderThickness}"
           CornerRadius="{TemplateBinding CornerRadius}"
           Background="{TemplateBinding Background}" RenderTransformOrigin="0,1">
                    <Border.RenderTransform>
                        <ScaleTransform x:Name="BackContentTransform" ScaleY="0"></ScaleTransform>
                    </Border.RenderTransform>
                 

                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"></RowDefinition>
                            <RowDefinition></RowDefinition>
                        </Grid.RowDefinitions>

                        <Rectangle Stretch="Fill" Fill="LightSteelBlue"></Rectangle>
                        <ToggleButton x:Name="FlipButtonAlternate" Margin="5" Padding="15,0"
                             Content="˅" FontWeight="Bold" FontSize="12" HorizontalAlignment="Right">
                        </ToggleButton>

                        <ContentPresenter Grid.Row="1"
                     Content="{TemplateBinding BackContent}">
                        </ContentPresenter>

                    </Grid>

                </Border>

            </Grid>

        </ControlTemplate>

控制设置scaley 从1,到0

 <DoubleAnimation Storyboard.TargetName="FrontContentTransform"
                       Storyboard.TargetProperty="ScaleY" To="1" ></DoubleAnimation>

                            

                                <DoubleAnimation Storyboard.TargetName="BackContentTransform"
                       Storyboard.TargetProperty="ScaleY" To="0" ></DoubleAnimation>

posted on 2012-09-24 09:39  GIS-MAN  阅读(183)  评论(0编辑  收藏  举报

导航