Переключение между двумя визуальными состояниями (WP7.1) - PullRequest
1 голос
/ 14 марта 2012

Я думаю, что то, что я делаю, довольно просто, наверное, я что-то упускаю.

У меня есть StackPanel внутри другой StackPanel. То, что я хочу сделать, это скрыть / показать внутреннюю при нажатии на внешнюю.

У меня есть 2 состояния в смеси. Первый делает StackPanel свернутым, другой - расширенным.

Я добавил 2 поведения (GoToStateBaheviour) к внешней StackPanel и назначил их триггеры для события MouseLeftButtonDown. В первом поведении в Условиях я проверяю, свернута ли внутренняя панель StackPanel, если она переключается в состояние «Развернуто». Другое поведение работает наоборот - в Условиях я проверяю, видна ли внутренняя панель StackPanel, если она переключается в состояние Collapsed.

Теперь оба эти поведения индивидуально работают. Но вместе взятых, не случайно. Я попытался изменить имя события одного из них на «ManipulationDelta», и затем оба начали работать - но чтобы активировать одно, я должен попытаться перетащить его.

Похоже, что 2 поведения, привязанные к одному и тому же событию, вызывают проблемы. Что бы вы порекомендовали?

EDIT

Я загрузил все решение, чтобы вы могли открыть его в Blend http://leteckaposta.cz/800017526

(проект для WPF, в отличие от того, который у меня есть для WP7, но это не имеет значения) Я изменил поведение на ChangePropertyAction, что должно облегчить чтение. Их два - оба реагируют на MouseLeftButtonDown со свойством Condition for Visibility. один из них меняет его на Visible, другой на Collapsed. Но только один из них работает. Я подозреваю, что это всегда «верхний» (тот, который идет первым). Не стесняйтесь проверить это сами

код

<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 голосов
/ 17 мая 2013

Происходит то, что ваши триггеры срабатывают последовательно, а не одновременно.Вот что происходит, событие

  1. MouseLeftButtonDown сработало
  2. Первый триггер активируется, проверяет Visibility, он виден, поэтому он меняет его на Свернутый
  3. ВторойТриггер активирует, проверяет Visibility, что он свернут, поэтому он меняет его на Visible

Чистый результат в том, что он застрял в состоянии 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}"
0 голосов
/ 27 апреля 2012

Как вы прокомментировали в ответе Криса В. , когда вы помещаете оба триггера в одно и то же событие, они конкурируют друг с другом и отменяют друг друга. Вы можете проверить это, используя 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;
}
...