WPF:如何将超链接和弹出窗口组合成弹出超链接?

WPF:如何将超链接和弹出窗口组合成弹出超链接?,wpf,hyperlink,popup,Wpf,Hyperlink,Popup,现在我有三件: <TextBlock Margin="2, 0, 0, 0" VerticalAlignment="Center"> <Hyperlink Click="UpdateHyperlinkOnClick"> <Run Text="Some text"/> </Hyperlink> </TextBlock> <Popup Name="UpdatePopup" StaysOpen="Fal

现在我有三件:

<TextBlock Margin="2, 0, 0, 0" VerticalAlignment="Center">
    <Hyperlink Click="UpdateHyperlinkOnClick">
        <Run Text="Some text"/>
    </Hyperlink>
</TextBlock>

<Popup Name="UpdatePopup" StaysOpen="False" Placement="Mouse" AllowsTransparency="True" PopupAnimation="Slide">
    <ContentControl Style="{StaticResource PopupContentStyle}">
        <TextBlock Margin="10" TextWrapping="Wrap" MaxWidth="600">
            <Run Text="{Binding Path=UpdateMessage, Mode=OneWay}"></Run>
            <Hyperlink Click="InstallClick"><Run Text="Some text"/></Hyperlink>
        </TextBlock>
    </ContentControl>
</Popup>

private void UpdateHyperlinkOnClick(object sender, RoutedEventArgs e)
{
    this.UpdatePopup.IsOpen = true;
}

私有void UpdateHyperlinkOnClick(对象发送方,RoutedEventTargs e)
{
this.UpdatePopup.IsOpen=true;
}
我想摆脱超链接中的点击事件,它的实现和必须命名一个弹出控件

理想情况下,我想要这样的东西:

<PopupHyperLink>
    <Hyperlink>
        <Run Text="{x:Static properties:Resources.UpdateIsAvailableText}"/>
    </Hyperlink>
    <Popup StaysOpen="False" Placement="Mouse" AllowsTransparency="True" PopupAnimation="Slide">
        <ContentControl Style="{StaticResource PopupContentStyle}">
            <TextBlock Margin="10" TextWrapping="Wrap" MaxWidth="600">
                <Run Text="{Binding Path=UpdateMessage, Mode=OneWay}"></Run>
                <Hyperlink Click="InstallClick"><Run Text="{x:Static properties:Resources.InstallText}"/></Hyperlink>
            </TextBlock>
        </ContentControl>
    </Popup>
</PopupHyperLink>

你知道怎么做吗


谢谢

据我所知,在这种情况下,您希望避免代码落后。但是,没有一种持久状态,我们可以使用
触发器或
绑定将
IsOpen
保持为true。您还可以调用命令,该命令应将
IsOpen
设置为true。然而,这需要在codebehind中使用一些命令,这仍然是您想要避免的

我刚刚考虑过在本例中使用
EventTrigger
,它允许您启动动画,使用
BooleanAnimationUsingKeyFrames
,您可以轻松地将属性设置为
true
false
。问题是
情节提要。应该设置目标
。在
样式
上下文中,我们不能使用
情节提要。TargetName
,因为
情节提要
不是
框架元素
,我们不能使用指定的
元素名
相对资源
的绑定。绑定
故事板.Target
的唯一方法是使用具有指定
源的绑定。通常将其设置为
静态资源
动态资源
(或直接)。因此,您应该将
弹出窗口
放置为具有指定ResourceKey的资源(这也是我们通常推荐的做法)。以下是代码详细信息:

<Window.Resources>
  <Popup x:Key="pop" Name="p2" StaysOpen="False" Placement="Mouse" 
         AllowsTransparency="True" PopupAnimation="Slide">
      <ContentControl Style="{StaticResource PopupContentStyle}">
        <TextBlock Margin="10" TextWrapping="Wrap" MaxWidth="600">
            <Run Text="{Binding Path=UpdateMessage, Mode=OneWay}"></Run>
            <Hyperlink Click="InstallClick">
              <Run Text="{x:Static properties:Resources.InstallText}"/>
            </Hyperlink>
        </TextBlock>
      </ContentControl>
  </Popup>
</Window.Resources>

<TextBlock>
  <Hyperlink>
    <Hyperlink.Style>
       <Style TargetType="Hyperlink">
         <Style.Triggers>
           <EventTrigger RoutedEvent="Click">
             <BeginStoryboard>
               <Storyboard>
                 <BooleanAnimationUsingKeyFrames 
                    Storyboard.Target="{Binding Source={StaticResource pop}}"
                    Storyboard.TargetProperty="IsOpen" Duration="0:0:0">
                      <DiscreteBooleanKeyFrame Value="True" KeyTime="0:0:0"/>
                 </BooleanAnimationUsingKeyFrames>
                </Storyboard>
              </BeginStoryboard>
            </EventTrigger>
          </Style.Triggers>
         </Style>
      </Hyperlink.Style>
      <Run Text="{x:Static properties:Resources.UpdateIsAvailableText}"/>
   </Hyperlink>
 </TextBlock>


请注意,通过这种方式,
IsOpen
已设置动画。因此,要通过codebehind中的本地设置覆盖它,必须首先删除动画值(搜索如何覆盖WPF中的动画值)。

这是我想要实现的第一个版本。这里肯定有漏洞,我会尝试更新这个答案

使用下面描述的方法,我现在可以编写这样的XAML代码并感到高兴:)


这似乎正是我的应用程序所需要的:

  • 能够为超链接提供文本
  • 为这个特殊的超链接指定我的自定义弹出窗口(对于不同的超链接,它可以是不同的-这就是全部想法)
  • 我使用此控件的位置没有代码隐藏
  • 总体而言:

  • 具有两个属性(弹出窗口和超链接文本)的已定义自定义控件
  • 在Generic.XAML中定义了XAML
  • 定义OnClick(通过迭代UI元素实现-不确定是否更容易做得更好)
  • 缺点:

  • 由于某些原因,只有在第一次打开VS/Blend时,VS和Blend才能可视化此控件。一旦我第二次编译它,它就会显示为空
  • 我不确定这是否是实现类似内容的最佳方式。有什么改进的办法吗
  • 实施:

    我定义了一个自定义控件:

    /// <summary>The hyperlink popup.</summary>
    public class HyperlinkPopup : ContentControl
    {
        #region Constants and Fields
    
        /// <summary>The popup property.</summary>
        public static readonly DependencyProperty PopupProperty = DependencyProperty.Register(
            "Popup", 
            typeof(object), 
            typeof(HyperlinkPopup), 
            new UIPropertyMetadata(null));
    
        /// <summary>The popup property.</summary>
        public static readonly DependencyProperty HyperlinkTextProperty = DependencyProperty.Register(
            "HyperlinkText", 
            typeof(string), 
            typeof(HyperlinkPopup), 
            new PropertyMetadata(default(string)));
    
        #endregion
    
        #region Constructors and Destructors
    
        /// <summary>Initializes static members of the <see cref="HyperlinkPopup"/> class.</summary>
        static HyperlinkPopup()
        {
            DefaultStyleKeyProperty.OverrideMetadata(
                typeof(HyperlinkPopup), 
                new FrameworkPropertyMetadata(typeof(HyperlinkPopup)));
        }
    
        #endregion
    
        #region Public Properties
    
        /// <summary>Gets or sets the popup.</summary>
        public object Popup
        {
            get
            {
                return (object)this.GetValue(PopupProperty);
            }
    
            set
            {
                this.SetValue(PopupProperty, value);
            }
        }
    
        /// <summary>Gets or sets the text.</summary>
        public string HyperlinkText
        {
            get
            {
                return (string)this.GetValue(HyperlinkTextProperty);
            }
    
            set
            {
                this.SetValue(HyperlinkTextProperty, value);
            }
        }
    
        #endregion
    }
    
    ///超链接弹出窗口。
    公共类HyperlinkPopup:ContentControl
    {
    #区域常数和字段
    ///弹出窗口属性。
    公共静态只读DependencyProperty PopupProperty=DependencyProperty.Register(
    “弹出窗口”,
    类型(对象),
    类型(HyperlinkPopup),
    新的UIPropertyMetadata(空);
    ///弹出窗口属性。
    公共静态只读DependencyProperty HyperlinkTextProperty=DependencyProperty.Register(
    “超链接文本”,
    类型(字符串),
    类型(HyperlinkPopup),
    新属性元数据(默认值(字符串));
    #端区
    #区域构造函数和析构函数
    ///初始化类的静态成员。
    静态超链接弹出窗口()
    {
    DefaultStyleKeyProperty.OverrideMetadata(
    类型(HyperlinkPopup),
    新的FrameworkPropertyMetadata(typeof(HyperlinkPopup));
    }
    #端区
    #区域公共财产
    ///获取或设置弹出窗口。
    公共对象弹出窗口
    {
    收到
    {
    返回(对象)this.GetValue(PopupProperty);
    }
    设置
    {
    此.SetValue(PopupProperty,value);
    }
    }
    ///获取或设置文本。
    公共字符串超链接文本
    {
    收到
    {
    返回(字符串)this.GetValue(HyperlinkTextProperty);
    }
    设置
    {
    this.SetValue(HyperlinkTextProperty,value);
    }
    }
    #端区
    }
    
    OnClick事件的处理方式如下(有点老套,很乐意学习如何做得更好):

    ///超链接弹出事件。
    公共部分类HyperlinkPopupEvents
    {
    #区域方法
    ///单击后,将显示超链接。
    ///发送者。
    ///e。
    私有void HyperlinkOnClick(对象发送方,RoutedEventArgs e)
    {
    //定位ContentPresenter
    var hyperLink=(hyperLink)发送方;
    var grid=visualtreeheloper.GetParent(hyperLink.Parent)作为UIElement;
    Assert(grid!=null,“元素为null”);
    断言(
    VisualTreeHelper.GetChildrenCount(网格)==2,
    “在我们的自定义HyperlinkPopup中,网格下必须只有2个子项”);
    var popup=(popup)VisualTreeHelp
    
    /// <summary>The hyperlink popup.</summary>
    public class HyperlinkPopup : ContentControl
    {
        #region Constants and Fields
    
        /// <summary>The popup property.</summary>
        public static readonly DependencyProperty PopupProperty = DependencyProperty.Register(
            "Popup", 
            typeof(object), 
            typeof(HyperlinkPopup), 
            new UIPropertyMetadata(null));
    
        /// <summary>The popup property.</summary>
        public static readonly DependencyProperty HyperlinkTextProperty = DependencyProperty.Register(
            "HyperlinkText", 
            typeof(string), 
            typeof(HyperlinkPopup), 
            new PropertyMetadata(default(string)));
    
        #endregion
    
        #region Constructors and Destructors
    
        /// <summary>Initializes static members of the <see cref="HyperlinkPopup"/> class.</summary>
        static HyperlinkPopup()
        {
            DefaultStyleKeyProperty.OverrideMetadata(
                typeof(HyperlinkPopup), 
                new FrameworkPropertyMetadata(typeof(HyperlinkPopup)));
        }
    
        #endregion
    
        #region Public Properties
    
        /// <summary>Gets or sets the popup.</summary>
        public object Popup
        {
            get
            {
                return (object)this.GetValue(PopupProperty);
            }
    
            set
            {
                this.SetValue(PopupProperty, value);
            }
        }
    
        /// <summary>Gets or sets the text.</summary>
        public string HyperlinkText
        {
            get
            {
                return (string)this.GetValue(HyperlinkTextProperty);
            }
    
            set
            {
                this.SetValue(HyperlinkTextProperty, value);
            }
        }
    
        #endregion
    }
    
    /// <summary>The hyperlink popup events.</summary>
    public partial class HyperlinkPopupEvents
    {
        #region Methods
    
        /// <summary>The hyperlink on click.</summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        private void HyperlinkOnClick(object sender, RoutedEventArgs e)
        {
            // Locate ContentPresenter
            var hyperLink = (Hyperlink)sender;
            var grid = VisualTreeHelper.GetParent(hyperLink.Parent) as UIElement;
            Debug.Assert(grid != null, "element is null");
            Debug.Assert(
                VisualTreeHelper.GetChildrenCount(grid) == 2,
                "There must be only 2 children under grid in our custom HyperlinkPopup");
    
            var popup = (Popup)VisualTreeHelper.GetChild(grid, 1);
            popup.IsOpen = true;
        }
    
        #endregion
    }
    
    <Style TargetType="{x:Type local:HyperlinkPopup}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:HyperlinkPopup}">
                    <Grid>
                        <TextBlock VerticalAlignment="Center">
                            <Hyperlink Click="HyperlinkOnClick">
                                <Run Text="{TemplateBinding HyperlinkText}"/>
                            </Hyperlink>
                        </TextBlock>
                        <Popup StaysOpen="False" Placement="Mouse" AllowsTransparency="True" PopupAnimation="Slide">
                            <ContentControl Style="{StaticResource PopupContentStyle}">
                                <ContentPresenter ContentSource="Popup"/>
                            </ContentControl>
                        </Popup>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>