【问题标题】:How does the Silverlight combobox disappear the way it does?Silverlight 组合框是如何消失的?
【发布时间】:2011-11-15 23:42:27
【问题描述】:

在 silverlight 中,如果我展开组合框然后将鼠标光标移开,无论我在哪里单击 silverlight 应用程序,组合框下拉菜单都会再次折叠。它是如何做到这一点的,我可以自己复制它吗?

【问题讨论】:

    标签: c# silverlight xaml combobox


    【解决方案1】:

    在 Silverlight 中,这是通过 VisualStateManager(简称 VSM)中的状态完成的。

    Silverlight Introduces the VSM

    这里是 ComboBox 的模板,您可以使用它来查看它如何与 VSM 一起工作以实现这一目标并使用它:

    <Style TargetType="ComboBox">
                <Setter Property="Padding" Value="6,2,25,2"/>
                <Setter Property="Background" Value="#FF1F3B53"/>
                <Setter Property="HorizontalContentAlignment" Value="Left"/>
                <Setter Property="BorderThickness" Value="1"/>
                <Setter Property="TabNavigation" Value="Once"/>
                <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
                <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
                <Setter Property="BorderBrush">
                    <Setter.Value>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                            <GradientStop Color="#FFA3AEB9" Offset="0"/>
                            <GradientStop Color="#FF8399A9" Offset="0.375"/>
                            <GradientStop Color="#FF718597" Offset="0.375"/>
                            <GradientStop Color="#FF617584" Offset="1"/>
                        </LinearGradientBrush>
                    </Setter.Value>
                </Setter>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ComboBox">
                            <Grid>
                                <Grid.Resources>
                                    <Style x:Name="comboToggleStyle" TargetType="ToggleButton">
                                        <Setter Property="Foreground" Value="#FF333333"/>
                                        <Setter Property="Background" Value="#FF1F3B53"/>
                                        <Setter Property="BorderBrush">
                                            <Setter.Value>
                                                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                    <GradientStop Color="#FFA3AEB9" Offset="0"/>
                                                    <GradientStop Color="#FF8399A9" Offset="0.375"/>
                                                    <GradientStop Color="#FF718597" Offset="0.375"/>
                                                    <GradientStop Color="#FF617584" Offset="1"/>
                                                </LinearGradientBrush>
                                            </Setter.Value>
                                        </Setter>
                                        <Setter Property="BorderThickness" Value="1"/>
                                        <Setter Property="Padding" Value="3"/>
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate TargetType="ToggleButton">
                                                    <Grid>
                                                        <VisualStateManager.VisualStateGroups>
                                                            <VisualStateGroup x:Name="CommonStates">
                                                                <VisualState x:Name="Normal"/>
                                                                <VisualState x:Name="MouseOver">
                                                                    <Storyboard>
                                                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundOverlay"/>
                                                                        <ColorAnimation Duration="0" To="#7FFFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
                                                                        <ColorAnimation Duration="0" To="#CCFFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
                                                                        <ColorAnimation Duration="0" To="#F2FFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
                                                                    </Storyboard>
                                                                </VisualState>
                                                                <VisualState x:Name="Pressed">
                                                                    <Storyboard>
                                                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundOverlay2"/>
                                                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Highlight"/>
                                                                        <ColorAnimation Duration="0" To="#E5FFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
                                                                        <ColorAnimation Duration="0" To="#BCFFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
                                                                        <ColorAnimation Duration="0" To="#6BFFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
                                                                        <ColorAnimation Duration="0" To="#F2FFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient"/>
                                                                    </Storyboard>
                                                                </VisualState>
                                                                <VisualState x:Name="Disabled"/>
                                                            </VisualStateGroup>
                                                            <VisualStateGroup x:Name="CheckStates">
                                                                <VisualState x:Name="Checked">
                                                                    <Storyboard>
                                                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="BackgroundOverlay3"/>
                                                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Highlight"/>
                                                                        <DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="BackgroundGradient2"/>
                                                                        <ColorAnimation Duration="0" To="#E5FFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[1].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient2"/>
                                                                        <ColorAnimation Duration="0" To="#BCFFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[2].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient2"/>
                                                                        <ColorAnimation Duration="0" To="#6BFFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[3].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient2"/>
                                                                        <ColorAnimation Duration="0" To="#F2FFFFFF" Storyboard.TargetProperty="(Shape.Fill).(GradientBrush.GradientStops)[0].(GradientStop.Color)" Storyboard.TargetName="BackgroundGradient2"/>
                                                                    </Storyboard>
                                                                </VisualState>
                                                                <VisualState x:Name="Unchecked"/>
                                                            </VisualStateGroup>
                                                            <VisualStateGroup x:Name="FocusStates">
                                                                <VisualState x:Name="Focused">
                                                                    <Storyboard>
                                                                        <ObjectAnimationUsingKeyFrames Duration="0" Storyboard.TargetProperty="Visibility" Storyboard.TargetName="FocusVisualElement">
                                                                            <DiscreteObjectKeyFrame KeyTime="0">
                                                                                <DiscreteObjectKeyFrame.Value>
                                                                                    <Visibility>Visible</Visibility>
                                                                                </DiscreteObjectKeyFrame.Value>
                                                                            </DiscreteObjectKeyFrame>
                                                                        </ObjectAnimationUsingKeyFrames>
                                                                    </Storyboard>
                                                                </VisualState>
                                                                <VisualState x:Name="Unfocused"/>
                                                            </VisualStateGroup>
                                                        </VisualStateManager.VisualStateGroups>
                                                        <Rectangle x:Name="Background" Fill="{TemplateBinding Background}" RadiusY="3" RadiusX="3" Stroke="{TemplateBinding BorderBrush}" StrokeThickness="{TemplateBinding BorderThickness}"/>
                                                        <Rectangle x:Name="BackgroundOverlay" Fill="#FF448DCA" Opacity="0" RadiusY="3" RadiusX="3" Stroke="#00000000" StrokeThickness="{TemplateBinding BorderThickness}"/>
                                                        <Rectangle x:Name="BackgroundOverlay2" Fill="#FF448DCA" Opacity="0" RadiusY="3" RadiusX="3" Stroke="#00000000" StrokeThickness="{TemplateBinding BorderThickness}"/>
                                                        <Rectangle x:Name="BackgroundGradient" Margin="{TemplateBinding BorderThickness}" RadiusY="2" RadiusX="2" Stroke="#FFFFFFFF" StrokeThickness="1">
                                                            <Rectangle.Fill>
                                                                <LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
                                                                    <GradientStop Color="#FFFFFFFF" Offset="0"/>
                                                                    <GradientStop Color="#F9FFFFFF" Offset="0.375"/>
                                                                    <GradientStop Color="#E5FFFFFF" Offset="0.625"/>
                                                                    <GradientStop Color="#C6FFFFFF" Offset="1"/>
                                                                </LinearGradientBrush>
                                                            </Rectangle.Fill>
                                                        </Rectangle>
                                                        <Rectangle x:Name="BackgroundOverlay3" Fill="#FF448DCA" Opacity="0" RadiusY="3" RadiusX="3" Stroke="#00000000" StrokeThickness="{TemplateBinding BorderThickness}"/>
                                                        <Rectangle x:Name="BackgroundGradient2" Margin="{TemplateBinding BorderThickness}" Opacity="0" RadiusY="2" RadiusX="2" Stroke="#FFFFFFFF" StrokeThickness="1">
                                                            <Rectangle.Fill>
                                                                <LinearGradientBrush EndPoint=".7,1" StartPoint=".7,0">
                                                                    <GradientStop Color="#FFFFFFFF" Offset="0"/>
                                                                    <GradientStop Color="#F9FFFFFF" Offset="0.375"/>
                                                                    <GradientStop Color="#E5FFFFFF" Offset="0.625"/>
                                                                    <GradientStop Color="#C6FFFFFF" Offset="1"/>
                                                                </LinearGradientBrush>
                                                            </Rectangle.Fill>
                                                        </Rectangle>
                                                        <Rectangle x:Name="Highlight" IsHitTestVisible="false" Margin="{TemplateBinding BorderThickness}" Opacity="0" RadiusY="2" RadiusX="2" Stroke="#FF6DBDD1" StrokeThickness="1"/>
                                                        <ContentPresenter x:Name="contentPresenter" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                                        <Rectangle x:Name="FocusVisualElement" IsHitTestVisible="false" Margin="1" RadiusY="3.5" RadiusX="3.5" Stroke="#FF6DBDD1" StrokeThickness="1" Visibility="Collapsed"/>
                                                    </Grid>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </Grid.Resources>
                                <VisualStateManager.VisualStateGroups>
                                    <VisualStateGroup x:Name="CommonStates">
                                        <VisualState x:Name="Normal"/>
                                        <VisualState x:Name="MouseOver"/>
                                        <VisualState x:Name="Disabled">
                                            <Storyboard>
                                                <DoubleAnimation Duration="00:00:00" To=".55" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="DisabledVisualElement"/>
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                    <VisualStateGroup x:Name="FocusStates">
                                        <VisualState x:Name="Focused">
                                            <Storyboard>
                                                <DoubleAnimation Duration="00:00:00" To="1" Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="FocusVisualElement"/>
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="Unfocused"/>
                                        <VisualState x:Name="FocusedDropDown">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Duration="00:00:00" Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="PopupBorder">
                                                    <DiscreteObjectKeyFrame KeyTime="00:00:00">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <Visibility>Visible</Visibility>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                    <VisualStateGroup x:Name="ValidationStates">
                                        <VisualState x:Name="Valid"/>
                                        <VisualState x:Name="InvalidUnfocused">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
                                                    <DiscreteObjectKeyFrame KeyTime="0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <Visibility>Visible</Visibility>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                        <VisualState x:Name="InvalidFocused">
                                            <Storyboard>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility" Storyboard.TargetName="ValidationErrorElement">
                                                    <DiscreteObjectKeyFrame KeyTime="0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <Visibility>Visible</Visibility>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsOpen" Storyboard.TargetName="validationTooltip">
                                                    <DiscreteObjectKeyFrame KeyTime="0">
                                                        <DiscreteObjectKeyFrame.Value>
                                                            <System:Boolean>True</System:Boolean>
                                                        </DiscreteObjectKeyFrame.Value>
                                                    </DiscreteObjectKeyFrame>
                                                </ObjectAnimationUsingKeyFrames>
                                            </Storyboard>
                                        </VisualState>
                                    </VisualStateGroup>
                                </VisualStateManager.VisualStateGroups>
                                <Border x:Name="ContentPresenterBorder">
                                    <Grid>
                                        <ToggleButton x:Name="DropDownToggle" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" HorizontalAlignment="Stretch" HorizontalContentAlignment="Right" Margin="0" Style="{StaticResource comboToggleStyle}" VerticalAlignment="Stretch">
                                            <Path x:Name="BtnArrow" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z " HorizontalAlignment="Right" Height="4" Margin="0,0,6,0" Stretch="Uniform" Width="8">
                                                <Path.Fill>
                                                    <SolidColorBrush x:Name="BtnArrowColor" Color="#FF333333"/>
                                                </Path.Fill>
                                            </Path>
                                        </ToggleButton>
                                        <ContentPresenter x:Name="ContentPresenter" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                            <TextBlock Text=" "/>
                                        </ContentPresenter>
                                    </Grid>
                                </Border>
                                <Rectangle x:Name="DisabledVisualElement" Fill="White" IsHitTestVisible="false" Opacity="0" RadiusY="3" RadiusX="3"/>
                                <Rectangle x:Name="FocusVisualElement" IsHitTestVisible="false" Margin="1" Opacity="0" RadiusY="2" RadiusX="2" Stroke="#FF6DBDD1" StrokeThickness="1"/>
                                <Border x:Name="ValidationErrorElement" BorderBrush="#FFDB000C" BorderThickness="1" CornerRadius="1" Visibility="Collapsed">
                                    <ToolTipService.ToolTip>
                                        <ToolTip x:Name="validationTooltip" DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Template="{StaticResource ValidationToolTipTemplate}">
                                            <ToolTip.Triggers>
                                                <EventTrigger RoutedEvent="Canvas.Loaded">
                                                    <BeginStoryboard>
                                                        <Storyboard>
                                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="IsHitTestVisible" Storyboard.TargetName="validationTooltip">
                                                                <DiscreteObjectKeyFrame KeyTime="0">
                                                                    <DiscreteObjectKeyFrame.Value>
                                                                        <System:Boolean>true</System:Boolean>
                                                                    </DiscreteObjectKeyFrame.Value>
                                                                </DiscreteObjectKeyFrame>
                                                            </ObjectAnimationUsingKeyFrames>
                                                        </Storyboard>
                                                    </BeginStoryboard>
                                                </EventTrigger>
                                            </ToolTip.Triggers>
                                        </ToolTip>
                                    </ToolTipService.ToolTip>
                                    <Grid Background="Transparent" HorizontalAlignment="Right" Height="12" Margin="1,-4,-4,0" VerticalAlignment="Top" Width="12">
                                        <Path Data="M 1,0 L6,0 A 2,2 90 0 1 8,2 L8,7 z" Fill="#FFDC000C" Margin="1,3,0,0"/>
                                        <Path Data="M 0,0 L2,0 L 8,6 L8,8" Fill="#ffffff" Margin="1,3,0,0"/>
                                    </Grid>
                                </Border>
                                <Popup x:Name="Popup">
                                    <Border x:Name="PopupBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="3" HorizontalAlignment="Stretch" Height="Auto">
                                        <Border.Background>
                                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                                <GradientStop Color="#FFFFFFFF" Offset="0"/>
                                                <GradientStop Color="#FFFEFEFE" Offset="1"/>
                                            </LinearGradientBrush>
                                        </Border.Background>
                                        <ScrollViewer x:Name="ScrollViewer" BorderThickness="0" Padding="1">
                                            <ItemsPresenter/>
                                        </ScrollViewer>
                                    </Border>
                                </Popup>
                            </Grid>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
    

    【讨论】:

    • 我自己看过,但它并没有真正帮助,我仍然看不到组合框如何知道有人点击离开它,或者我错过了一种视觉状态这实际上是什么?
    【解决方案2】:

    如果您有 Expression Blend,您可以轻松了解它是如何完成的。

    只需创建一个 SL 项目,在表面添加ComboBox,右键单击它并选择编辑模板->制作副本,然后检查模板,它可能是在其中一个过渡/视觉上使用一些动画制作的状态经理。

    【讨论】:

    • 所有应有的尊重,但这有点无法回答/猜测应该是评论......
    • 如果 OP 不知道并且确实有 Blend,我肯定会将其归类为答案。
    【解决方案3】:

    关键是控件的模板使用了Popup控件,你可以在自己的控件中自己使用。

    http://msdn.microsoft.com/en-us/library/system.windows.controls.primitives.popup%28v=VS.95%29.aspx

    【讨论】:

    • 很有趣 - 我在面试时被问到这个问题
    • 对不起,我的问题可能有点含糊,我想知道的是组合框是如何知道的Silverlight 应用程序中的空间)。
    猜你喜欢
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多