WPF: доступ к элементам внутри ContentPresenter? - PullRequest
0 голосов
/ 09 июля 2010

Может кто-нибудь помочь мне с этим?У меня есть следующие настройки шаблона в WPF:

    <Style TargetType="{x:Type Label}" x:Key="NavLink">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate x:Name="NavLinkControlTemplate" TargetType="{x:Type Label}">
                    <Border x:Name="NavLinkBorder">
                        <ContentPresenter x:Name="NavLinkContent" Margin="4,4,4,4" />
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="NavLinkBorder" Property="Background" Value="#CCCCCC" />
                            <Setter Property="Cursor" Value="Hand" />
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="False">
                            <Setter TargetName="NavLinkBorder" Property="Background" Value="#EAEAEA" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Когда моя программа загружена, она автоматически создает список меток, которые служат в качестве меню навигации.Как видно из вышесказанного, когда мышь наводит курсор на одну из меток, цвет фона меняется.Единственная проблема с этим заключается в том, что у меня также есть контекстное меню, примененное к меткам, и когда я щелкаю правой кнопкой мыши, чтобы вызвать его, фон метки возвращается к исходному цвету вместо того, чтобы оставаться цветом MouseOver.

Я гуглил около часа или около того и не могу найти свойство триггера, которое проверит, нажата ли правая кнопка мыши, поэтому я предполагаю, что его нет.Я думаю, может быть, я смогу сделать это с помощью кода.

Я попробовал следующий код, но мне не повезло:

    // this event is being added to each label at runtime...
    tempLabel.MouseRightButtonUp += new MouseButtonEventHandler(NavLink_RightClicked);

    // this is the method that the right-click calls...
    private void NavLink_RightClicked(object sender, EventArgs e)
        {
            if (sender is Label)
            {
                currentContextLink = sender as Label;

                // the below line won't work because the ControlTemplate seems to be overwriting it...
                currentContextLink.Background = new SolidColorBrush(appFunctions.HexToColor("#FF0000"));
            }
        }

Я также попытался получить родителя Labelэлемент как Граница, но кажется, что, поскольку он настроен с помощью шаблона, родительский элемент Label на самом деле является StackPanel, в которой находятся все метки.

Может кто-нибудь помочь мне разобраться, как получить доступ к границеи изменить его цвет фона, или, может быть, направить меня в любом направлении, которое может помочь мне достичь этого?

Любая помощь очень ценится!

Ответы [ 3 ]

1 голос
/ 10 июля 2010

Вы можете добавить дополнительный триггер данных для проверки свойства IsOpen в ContextMenu с помощью привязки.

<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=ContextMenu.IsOpen}" Value="True">
    <Setter TargetName="NavLinkBorder"  Property="Background" Value="#CCCCCC" />
    <Setter Property="Cursor" Value="Hand" />
</DataTrigger>

Вы также можете избавиться от триггера MouseOver = "false" и просто установить Background = "# EAEAEA" в NavLinkBorder в качестве значения по умолчанию, которое вступит во владение, когда триггеры не активны.

Кроме того, вы можете переключить настройку цвета границы, чтобы использовать привязку шаблона, которая помогла бы вашему методу кода работать. В любом случае это хорошая практика, поскольку она делает ваши шаблоны более гибкими, поскольку для отдельных экземпляров Label можно установить разные значения фона. Вот стиль с некоторыми привязками TemplateBindings и триггером контекстного меню.

<Style TargetType="{x:Type Label}" x:Key="NavLink">
    <Setter Property="Background" Value="#EAEAEA" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate x:Name="NavLinkControlTemplate" TargetType="{x:Type Label}">
                <Border x:Name="NavLinkBorder" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
                        BorderThickness="{TemplateBinding BorderThickness}">
                    <ContentPresenter x:Name="NavLinkContent" Margin="4,4,4,4" />
                </Border>

                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="NavLinkBorder" Property="Background" Value="#CCCCCC" />
                        <Setter Property="Cursor" Value="Hand" />
                    </Trigger>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=ContextMenu.IsOpen}" Value="True">
                        <Setter TargetName="NavLinkBorder" Property="Background" Value="#CCCCCC" />
                        <Setter Property="Cursor" Value="Hand" />
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
0 голосов
/ 10 июля 2010

Спасибо за вашу помощь, но я немного новичок в WPF и не очень хорош в RoutedEvents. Я добавил первый раздел кода, как вы предложили, но при запуске я получаю следующую ошибку:

Невозможно преобразовать строку 'MouseRightButtonUp' в атрибуте 'RoutedEvent' в объект типа 'System.Windows.RoutedEvent'. RoutedEventConverter не может преобразовать из System.String. Ошибка в объекте 'System.Windows.EventTrigger' в файле разметки 'MyProgram; component / frmmain.xaml' Строка 62, позиция 43.

Мой код в стиле XAML теперь выглядит так:

    <Style TargetType="{x:Type Label}" x:Key="NavLink">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Label}">
                    <Border x:Name="NavLinkBorder" Background="#CCCCCC">
                        <ContentPresenter x:Name="NavLinkContent" Margin="4,4,4,4" />
                    </Border>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver" Value="True">
                            <Setter TargetName="NavLinkBorder" Property="Background" Value="#CCCCCC" />
                            <Setter Property="Cursor" Value="Hand" />
                        </Trigger>
                        <Trigger Property="IsMouseOver" Value="False">
                            <Setter TargetName="NavLinkBorder" Property="Background" Value="#EAEAEA" />
                        </Trigger>
                        <EventTrigger RoutedEvent="MouseRightButtonUp">
                            <BeginStoryboard>
                                <Storyboard>
                                    <ColorAnimation To="#FF0000" Duration="0" Storyboard.TargetName="NavLinkBorder" Storyboard.TargetProperty="(Background).(Color)"  />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

И я не публиковал это раньше, но вот как выглядит код, который генерирует мои ярлыки:

    Label tempLabel = new Label();
    tempLabel.Content = "My Link";
    tempLabel.ContextMenu = (ContextMenu)FindResource("NavContextMenu");
    tempLabel.FontSize = 12;
    tempLabel.Foreground = new SolidColorBrush(appFunctions.HexToColor("#000057"));
    tempLabel.Name = "myNavLink";
    tempLabel.Style = (Style)FindResource("NavLink");

    tempLabel.MouseLeftButtonUp += new MouseButtonEventHandler(NavLink_LeftClicked);
    tempLabel.MouseRightButtonUp += new MouseButtonEventHandler(NavLink_RightClicked);

    navPanel.Children.Add(tempLabel);

Когда я получаю ошибку, она выделяет эту строку из приведенного выше кода:

    tempLabel.Style = (Style)FindResource("NavLink");

Может быть, я неправильно прикрепляю стиль метки ...?

0 голосов
/ 09 июля 2010

Попробуйте это в своем стиле:

<EventTrigger RoutedEvent="MouseRightButtonUp">
    <BeginStoryboard>
        <Storyboard>
            <ColorAnimation To="#FF0000" Duration="0" Storyboard.TargetName="NavLinkBorder" Storyboard.TargetProperty="(Background).(Color)"  />
        </Storyboard>
    </BeginStoryboard>
</EventTrigger>

Обратите внимание, что <Trigger Property="IsMouseOver" Value="False"> изменит цвет обратно на #EAEAEA, как только мышь будет отключена.Если вы хотите, чтобы цвет «прилипал», измените ваш ControlTemplate следующим образом:

<Border x:Name="NavLinkBorder">
    <Border x:Name="NavLinkInnerBorder" Background="Transparent" >
        <ContentPresenter x:Name="NavLinkContent" Margin="4,4,4,4" />
    </Border>
</Border>

... и измените ColorAnimation так:

<ColorAnimation To="#FF0000" Duration="0" Storyboard.TargetName="NavLinkInnerBorder" Storyboard.TargetProperty="(Background).(Color)"  />
...