WPF:访问ContentPresenter中的元素?

时间:2010-07-09 17:05:07

标签: wpf controltemplate right-click

有人可以帮我解决这个问题吗?我在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颜色。

我用Google搜索了大约一个小时左右,似乎无法找到一个触发器属性来检查是否按下了鼠标右键,所以我假设没有一个。我想也许我可以通过代码完成这个。

我尝试过以下代码,但我没有运气:

    // 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 个答案:

答案 0 :(得分:1)

您可以添加其他数据触发器,以通过绑定检查ContextMenu的IsOpen属性。

<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”触发器,只需将NavLinkBorder上的Background =“#EAEAEA”设置为默认值,当没有触发器处于活动状态时将接管该值。

或者,您可以切换边框颜色设置以使用模板绑定,这将有助于您的代码方法工作。无论如何,这是一个很好的做法,因为它可以使您的模板更加灵活,因为可以在单个Label实例上设置不同的Background值。这是带有一些TemplateBindings的Style和添加的上下文菜单触发器。

<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>

答案 1 :(得分:0)

以你的风格尝试:

<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)"  />

答案 2 :(得分:0)

感谢您的帮助,但我对WPF不太熟悉,并且对RoutedEvents不太满意。我添加了你建议的第一部分代码,但是当我运行它时,我收到以下错误:

无法将属性“RoutedEvent”中的字符串“MouseRightButtonUp”转换为“System.Windows.RoutedEvent”类型的对象。 RoutedEventConverter无法从System.String转换。标记文件'MyProgram; component / frmmain.xaml'中对象'System.Windows.EventTrigger'出错'第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");

也许我没有正确附加标签的样式......?