【问题标题】:WPF: Accessing Elements within a ContentPresenter?WPF:访问 ContentPresenter 中的元素?
【发布时间】:2010-07-09 17:05:07
【问题描述】:

有人可以帮我解决这个问题吗?我在 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的父元素作为Border,但似乎由于它是通过模板设置的,因此Label的父元素实际上是我拥有的包含所有标签的StackPanel。

有人可以帮我弄清楚如何访问边框并更改其背景颜色,或者指导我朝任何可能帮助我完成此任务的方向吗?

非常感谢任何帮助!

【问题讨论】:

    标签: wpf controltemplate right-click


    【解决方案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 实例上设置不同的背景值。这是添加了一些 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>
    

    【讨论】:

    • 约翰,非常感谢!背景颜色现在保持不变;但是,仍然存在一个小错误。由于我所有的标签共享相同的上下文菜单,当它打开时,所有标签的背景颜色都会发生变化,而不仅仅是我点击的那个。有没有办法只识别源元素,还是应该为每个标签创建单独的上下文菜单?
    • 没关系,约翰,正如您所说,我能够使用代码来确定上下文菜单何时打开和关闭并更改发件人的背景来完成此任务!非常感谢!
    【解决方案2】:

    以你的风格试试这个:

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

    请注意,一旦鼠标移开,&lt;Trigger Property="IsMouseOver" Value="False"&gt; 会将颜色更改回 #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)"  />
    

    【讨论】:

    • 请参阅下面的更多问题。此评论框空间不足,无法全部发布。
    【解决方案3】:

    感谢您的帮助,但我对 WPF 有点陌生,对 RoutedEvents 不太熟悉。我按照您的建议添加了第一部分代码,但是当我运行它时,出现以下错误:

    无法将属性“RoutedEvent”中的字符串“MouseRightButtonUp”转换为“System.Windows.RoutedEvent”类型的对象。 RoutedEventConverter 无法从 System.String 转换。标记文件“MyProgram;component/frmmain.xaml”第 62 行位置 43 中的对象“System.Windows.EventTrigger”出错。

    我的 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");
    

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

    【讨论】:

      猜你喜欢
      • 2014-12-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 1970-01-01
      • 2011-05-13
      • 2019-06-14
      相关资源
      最近更新 更多