Почему мои действия на доске объявлений пропускаются при срабатывании триггера - PullRequest
0 голосов
/ 19 октября 2019

У меня есть Tabcontrol, который я пытаюсь добавить действия на основе триггеров.

Используя перенаправленные события, я могу заставить свою раскадровку срабатывать, и мои действия реагируют так, как задумано. Теперь я пытаюсь предотвратить запуск действий раскадровки для определенного заголовка вкладки, если этот заголовок выбран.

Это заставило меня отойти от перенаправленных событий, поскольку я не могу использовать условие свойства иперенаправленное событие, чтобы определить, будет ли выполняться моя раскадровка.

Быстрая перемотка вперед, и теперь я наконец-то смог заставить IsMouseOver отвечать на запросы мыши. (Мои свойства фона изменяются и изменяются обратно, когда мышь входит и покидает заголовок tabitem. Думаю, я почти готов, но как только я добавляю ту же самую раскадровку, что и раньше, мой код решает стать ленивым и по какой-то причине пропустить его. Установщик фона все еще срабатывает, но раскадровка остается тихой.

Я пытался удалить установщик, но раскадровка по-прежнему не срабатывает.

Конец дня: я пытался установить стили для переходамежду всеми возможными комбинациями Is Mouse Over и Is Selected.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:Tenant_Tool_Analytics_Module.Resources.Components"
                    xmlns:controls="clr-namespace:Tenant_Tool_Analytics_Module.Resources.Components">
    <Style TargetType="{x:Type controls:NavigationElement}">
        <Setter Property="Template">


            <Setter.Value>
                <ControlTemplate TargetType="{x:Type controls:NavigationElement}">
                    <Border BorderBrush="Black" BorderThickness=".7"  x:Name="Bd">
                        <Grid Width="150" Height="50" Opacity="0.75" x:Name="NavigationElementGrid">


                            <Grid.Background >
                                <RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="2.0">
                                    <GradientStop Color="#006A4D" Offset="1.0"/>
                                    <GradientStop Color="#56be88" Offset=".2"/>
                                </RadialGradientBrush >
                            </Grid.Background>
                            <ContentControl Grid.Column="0" Content="{TemplateBinding Icon}"/>
                            <TextBlock x:Name="NavigationElementText" Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left" Text="{TemplateBinding LabelText}" FontFamily="Futura XBlkIt BT" FontSize="12"/>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="40"/>
                                <ColumnDefinition Width="*"/>
                            </Grid.ColumnDefinitions>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="50" />
                            </Grid.RowDefinitions>
                        </Grid>
                    </Border>
                    <!--
                    Trigger related to when the mouse is over the header
                        I would like it to Execute the doubleanimations 
                    -->
                    <ControlTemplate.Triggers>
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="True"/>
                                <!-- Missing condition: If selected = false -->
                            </MultiTrigger.Conditions>
                            <!-- Start BUG the bellow code does not execute -->
                            <MultiTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>

                                        <DoubleAnimation Storyboard.TargetName="NavigationElementGrid" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.3"/>
                                        <DoubleAnimation Storyboard.TargetName="NavigationElementText" Storyboard.TargetProperty="FontSize" To="14" Duration="0:0:0.3"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.EnterActions>
                            <!-- End BUG -->
                            <!-- The triggers are fireing becuase this is being set. -->
                            <Setter Property="Background" TargetName="Bd" Value="Blue"/>
                        </MultiTrigger>

                        <!-- 
                        When the mouse leaves I want it to return to it's original 
                        state. 


                        -->
                        <MultiTrigger>
                            <MultiTrigger.Conditions>
                                <Condition Property="IsMouseOver" Value="False"/>
                                <!-- Missing condition: If selected = false -->
                            </MultiTrigger.Conditions>
                            <!-- Start BUG the bellow code does not execute -->
                            <MultiTrigger.EnterActions>
                                <BeginStoryboard>
                                    <Storyboard>
                                        <DoubleAnimation Storyboard.TargetName="NavigationElementGrid" Storyboard.TargetProperty="Opacity" To=".75" Duration="0:0:0.3"/>
                                        <DoubleAnimation Storyboard.TargetName="NavigationElementText" Storyboard.TargetProperty="FontSize" To="12" Duration="0:0:0.3"/>
                                    </Storyboard>
                                </BeginStoryboard>
                            </MultiTrigger.EnterActions>
                            <!-- End BUG -->
                            <!-- The triggers are fireing becuase this is being set. -->
                            <Setter Property="Background" TargetName="Bd" Value="Red"/>
                        </MultiTrigger>

                        <!-- Missing two more MultiTriggers (very similar to above) for the cases of if the tab is selected.-->
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

Код позади

using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Tenant_Tool_Analytics_Module.Resources.Components
{
    public class NavigationElement : Control
    {
        public string LabelText
        {
            get
            {
                return (string)GetValue(LabelTextProperty);
            }
            set
            {
                SetValue(LabelTextProperty, value);
            }
        }

        public static readonly DependencyProperty LabelTextProperty =
            DependencyProperty.Register("LabelText", typeof(string), typeof(NavigationElement), new PropertyMetadata(string.Empty));

        public object Icon
        {
            get
            {
                return (object)GetValue(IconProperty);
            }
            set
            {
                SetValue(IconProperty, value);
            }
        }

        public static readonly DependencyProperty IconProperty =
            DependencyProperty.Register("Icon", typeof(object), typeof(NavigationElement), new PropertyMetadata(string.Empty));


        public System.Windows.Media.Brush BackgroundColour
        {
            get
            {
                return (System.Windows.Media.Brush)GetValue(BackgroundColourProperty);
            }
            set
            {
                SetValue(BackgroundColourProperty, value);
            }
        }

        public static readonly DependencyProperty BackgroundColourProperty =
            DependencyProperty.Register("BackgroundColour", typeof(System.Windows.Media.Brush), typeof(NavigationElement), new PropertyMetadata(Brushes.Black));

    }
}

Код реализации

<Window x:Class="Tenant_Tool_Analytics_Module.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Tenant_Tool_Analytics_Module"
        xmlns:views="clr-namespace:Tenant_Tool_Analytics_Module.Views"
        xmlns:controls="clr-namespace:Tenant_Tool_Analytics_Module.Resources.Components"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <DockPanel LastChildFill="True">
        <views:HeaderView x:Name="HeaderView" DockPanel.Dock="Top"/>
        <TabControl DockPanel.Dock="Left" TabStripPlacement="Left" Margin="0, 0, 0, 10">
            <TabItem Padding="0">
                <TabItem.Header>
                    <controls:NavigationElement LabelText="Stacking Plan" Icon="{StaticResource StackPlanIcon}"/>
                </TabItem.Header>
                <Button Content="HI"/>
            </TabItem>
            <TabItem Padding="0">
                <TabItem.Header>
                    <controls:NavigationElement LabelText="Tenant Profile" Icon="{StaticResource TenantProfileIcon}"/>
                </TabItem.Header>
                <Button Content="HI"/>
            </TabItem>
            <TabItem Padding="0">
                <TabItem.Header>
                    <controls:NavigationElement LabelText="Submarket" Icon="{StaticResource SubmarketIcon}"/>
                </TabItem.Header>
                <Button Content="HI"/>
            </TabItem>
            <TabItem Padding="0">
                <TabItem.Header>
                    <controls:NavigationElement LabelText="Industry" Icon="{StaticResource IndustryIcon}"/>
                </TabItem.Header>
                <Button Content="HI"/>
            </TabItem>
        </TabControl>
    </DockPanel>
</Window>

1 Ответ

1 голос
/ 20 октября 2019

Я думаю, вы не знали о том факте, что MultiDataTrigger объекты имеют как EnterActions, так и ExitActions. Вместо одного запуска MultiDataTrigger на true только с EnterActions и другого запуска MultiDataTrigger на false только с EnterActions, вы можете использовать только один MultiDataTrigger запуск на true с обоими EnterActions (чтобы перевести объект в ненормальное состояние) и ExitActions, чтобы перевести его обратно в нормальное состояние.

Коллекция Triggers теперь работает, как и ожидалось, и, в качестве бонуса, ее легче читать:

<ControlTemplate.Triggers>
    <MultiTrigger>
        <MultiTrigger.Conditions>
            <Condition Property="IsMouseOver" Value="True"/>
            <!-- Missing condition: If selected = false -->
        </MultiTrigger.Conditions>
        <MultiTrigger.EnterActions>
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="NavigationElementGrid"
                                     Storyboard.TargetProperty="Opacity"
                                     To="1"
                                     Duration="0:0:0.3"/>
                    <DoubleAnimation Storyboard.TargetName="NavigationElementText"
                                     Storyboard.TargetProperty="FontSize"
                                     To="14" Duration="0:0:0.3"/>
                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="BorderBackgroundBrush"
                                                  Storyboard.TargetProperty="Color">
                        <DiscreteColorKeyFrame KeyTime="0" Value="Blue"/>
                    </ColorAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </MultiTrigger.EnterActions>
        <MultiTrigger.ExitActions>
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="NavigationElementGrid"
                                     Storyboard.TargetProperty="Opacity"
                                     To=".75"
                                     Duration="0:0:0.3"/>
                    <DoubleAnimation Storyboard.TargetName="NavigationElementText"
                                     Storyboard.TargetProperty="FontSize"
                                     To="12"
                                     Duration="0:0:0.3"/>
                    <ColorAnimationUsingKeyFrames Storyboard.TargetName="BorderBackgroundBrush"
                                                  Storyboard.TargetProperty="Color">
                        <DiscreteColorKeyFrame KeyTime="0" Value="Red"/>
                    </ColorAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </MultiTrigger.ExitActions>
    </MultiTrigger>
    <!-- Missing two more MultiTriggers (very similar to above) for the cases of if the tab is selected.-->
</ControlTemplate.Triggers>

Также обратите внимание, как я использовал ColorAnimationUsingKeyFrames для изменения свойства Border.Background без необходимости Setter в другом Trigger. Таким образом, все изменения выполняются в одном Storyboard. Чтобы это работало, вам просто нужно присвоить именованное SolidColorBrush вашему "Bd" Border:

<Border.Background>
    <SolidColorBrush x:Name="BorderBackgroundBrush" Color="Red"></SolidColorBrush>
</Border.Background>

Чтобы запретить воспроизведение Storyboard, если выбран предок TabItem,Я предлагаю вам добавить логическое значение IsSelected DependencyProperty к вашему NavigationElement, чтобы вы могли привязать это свойство к его TabItem предку, добавив Setter в свой Style следующим образом:

<Setter Property="IsSelected" Value="{Binding IsSelected, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=TabItem}}"/>

И вам просто нужно добавить условие в MultiDataTrigger (но вы уже поняли это):

    <Condition Property="IsMouseOver" Value="True"/>
    <Condition Property="IsSelected" Value="False"/>

Sidenote : я рекомендую вам обернутьи отступ для ваших атрибутов XAML, чтобы избежать длинных строк XAML, которые заставляют вас прокручивать. Помимо повышенной читабельности, каждый атрибут XAML в новой строке более удобен для контроля версий, поскольку одно изменение атрибута влияет только на одну строку.

...