两种视觉状态之间的混合切换(WP7.1)

时间:2012-03-14 15:39:05

标签: c# windows-phone-7 xaml expression-blend behavior

我认为我所做的事情相当简单,我想我只是错过了一些东西。

我在另一个StackPanel内部有一个StackPanel。我想要做的是在点击一个外部时隐藏/显示内部的一个。

我在混合中有2个状态。首先使StackPanel折叠,另一个展开。

我向外部StackPanel添加了2个行为(GoToStateBaheviour)并将其触发器分配给MouseLeftButtonDown事件。在条件中的第一个行为中,我检查内部StackPanel是否已折叠,如果是,则切换到Expanded状态。 其他行为反之亦然 - 在条件中我检查内部StackPanel是否可见,如果是,则切换到Collapsed状态。

现在这两种行为都可以正常工作。但结合起来,不是机会。我试图将其中一个的事件名称更改为“ManipulationDelta”,然后两者都开始工作 - 但要激活我必须尝试拖动它。

似乎有2个行为附加到同一事件导致麻烦。你会推荐什么?

修改

我上传了整个解决方案,因此您可以在Blend中打开它 http://leteckaposta.cz/800017526

(该项目适用于WPF,而不是我对WP7的项目,但这不重要) 我将行为更改为ChangePropertyAction,这应该使它更容易阅读。它们有两个 - 都对MouseLeftButtonDown做出反应,其中包含Visibility属性。其中一个将其更改为Visible,另一个更改为Collapsed。 但只有其中一个有效。我怀疑它总是“上层”(首先出现的那个)。随意测试一下

CODE

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
    x:Class="WpfApplication1.MainWindow"
    x:Name="Window"
    Title="MainWindow"
    Width="640" Height="480">

    <Grid x:Name="LayoutRoot">
        <StackPanel Height="168" Width="305" HorizontalAlignment="Left" VerticalAlignment="Top" Background="#FF7C7070">
            <TextBlock Height="59" TextWrapping="Wrap" Text="Outter">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="MouseLeftButtonDown">
                        <i:Interaction.Behaviors>
                            <ei:ConditionBehavior>
                                <ei:ConditionalExpression>
                                    <ei:ComparisonCondition LeftOperand="{Binding Visibility, ElementName=stackPanel}" Operator="Equal">
                                        <ei:ComparisonCondition.RightOperand>
                                            <Visibility>Visible</Visibility>
                                        </ei:ComparisonCondition.RightOperand>
                                    </ei:ComparisonCondition>
                                </ei:ConditionalExpression>
                            </ei:ConditionBehavior>
                        </i:Interaction.Behaviors>
                        <ei:ChangePropertyAction TargetObject="{Binding ElementName=stackPanel}" PropertyName="Visibility">
                            <ei:ChangePropertyAction.Value>
                                <Visibility>Collapsed</Visibility>
                            </ei:ChangePropertyAction.Value>
                        </ei:ChangePropertyAction>
                    </i:EventTrigger>
                    <i:EventTrigger EventName="MouseLeftButtonDown">
                        <i:Interaction.Behaviors>
                            <ei:ConditionBehavior>
                                <ei:ConditionalExpression>
                                    <ei:ComparisonCondition LeftOperand="{Binding Visibility, ElementName=stackPanel}" Operator="NotEqual">
                                        <ei:ComparisonCondition.RightOperand>
                                            <Visibility>Visible</Visibility>
                                        </ei:ComparisonCondition.RightOperand>
                                    </ei:ComparisonCondition>
                                </ei:ConditionalExpression>
                            </ei:ConditionBehavior>
                        </i:Interaction.Behaviors>
                        <ei:ChangePropertyAction TargetObject="{Binding ElementName=stackPanel}" PropertyName="Visibility">
                            <ei:ChangePropertyAction.Value>
                                <Visibility>Visible</Visibility>
                            </ei:ChangePropertyAction.Value>
                        </ei:ChangePropertyAction>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </TextBlock>
            <StackPanel x:Name="stackPanel" Height="106" RenderTransformOrigin="0.489,-0.842" Background="#FF708B7C" Visibility="Hidden">
                <TextBlock Height="50" Margin="74,0,65,0" TextWrapping="Wrap" Text="Inner"/>
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

2 个答案:

答案 0 :(得分:0)

正如您在Chris W.'s answer中所评论的那样,当您将两个触发器放在同一个事件中时,它们会相互竞争并相互抵消。您可以在其中一个触发器上使用MouseLeftButtonUp来验证这一点。

事件背后的简单代码可以解决此问题。

<强> XAML

<Grid x:Name="LayoutRoot">
    <StackPanel Background="Red" MouseLeftButtonDown="OnMouseLeftButtonDown">
        <TextBlock FontSize="22" Text="Outter" />
        <StackPanel x:Name="stackPanel"
                    Height="75"
                    Background="Yellow">
            <TextBlock FontSize="22" Text="Inner" />
        </StackPanel>
    </StackPanel>
</Grid>

代码背后

private void OnMouseLeftButtonDown( object sender, MouseButtonEventArgs e )
{
    stackPanel.Visibility = stackPanel.Visibility == Visibility.Visible
                                    ? Visibility.Collapsed
                                    : Visibility.Visible;

    e.Handled = true;
}

答案 1 :(得分:0)

发生的事情是你的触发器按顺序而不是同时触发。这是正在发生的事情,

  1. 发起了MouseLeftButtonDown事件
  2. 第一个触发器激活,检查Visibility,它是可见的,因此它将其更改为折叠
  3. 第二次触发器激活,检查Visibility它是否已折叠,因此将其更改为“可见”
  4. 最终结果是它处于Visible状态。您可以通过更改触发器的顺序来验证这一点 - 结果将卡在折叠状态。

    对于每个实例,不需要代码隐藏的一种方法是使用{翻转'可见到折叠的Converter。然后,您可以使用ChangePropertyAction设置一个值,该值是通过此转换器的绑定确定的,例如

    <i:Interaction.Triggers>
         <i:EventTrigger EventName="Tap">
            <ec:ChangePropertyAction 
                TargetName="stackPanel"
                PropertyName="Visibility"
                Value="{Binding Visibility, 
                    Converter={StaticResource VisibilityToOpposite}, 
                    ElementName=stackPanel}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
    

    转换器看起来像这样,

    public class VisibilityToOpposite : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo)
        {
            Visibility vis = (Visibility)value;
            return (vis == Visibility.Collapsed) ? Visibility.Visible : Visibility.Collapsed;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultureInfo)
        {
            throw new NotImplementedException();
        }
    }
    

    这种方法的优点在于转换器可以重复使用,也不仅限于两种状态,例如。

    public class StringToNextString : System.Windows.Data.IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo)
        {
            string s = (string)value;
            List<string> allStrings = (parameter as string).Split(new char[] { '|' }).ToList();
            // Find the index of the next string along
            int i = allStrings.IndexOf(s);
            i = (i + 1) % allStrings.Count;
            return allStrings[i];
        }
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo cultureInfo)
        {
            throw new NotImplementedException();
        }
    }
    

    然后使用管道分隔字符串的ConverterParameter调用例如。

    Value="{Binding Text, ConverterParameter=one|two|three, 
        Converter={StaticResource StringToNextString}, 
        ElementName=stackPanel}"