2014-09-27 20 views
0

現在我有這三件:WPF:如何將Hyperlink和Popup結合成PopupHyperlink?

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

我想在超鏈接,其實施具有命名彈出控制擺脫Click事件。

理想情況下,我想有這樣的事情:

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

任何想法如何做這樣的事情?

謝謝!

回答

0

這是我想要實現的第一個版本。肯定有錯誤在這裏,我會盡量更新這個答案。

與下面描述的方法,我現在可以寫這樣的XAML代碼和快樂:)

<popupControl:HyperlinkPopup Margin="2, 0, 0, 0" HyperlinkText="{x:Static properties:Resources.UpdateIsAvailableText}"> 
    <popupControl:HyperlinkPopup.Popup> 
     <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> 
    </popupControl:HyperlinkPopup.Popup> 
</popupControl:HyperlinkPopup> 

這似乎正是我需要爲我的應用程序:

  1. 有能力提供一個文本對於超鏈接
  2. 指定我對此特定超鏈接的自定義彈出框(對於不同的超鏈接可以不同 - 這是整個想法)
  3. 沒有代碼在這裏我使用這個控制

總體地方:

  1. 具有兩個屬性(彈出和HyperlinkText)
  2. 在Generic.xaml
  3. 定義的OnClick定義XAML(可通過迭代通過執行定義的自定義控制UI元素 - 不確定是否更容易做到這一點)

缺點:

  1. 由於某些原因,VS和Blend都只能在第一次打開VS/Blend時可視化這個控件。一旦我編譯它第二次顯示爲空
  2. 不知道這是否是實現這樣的事情的最佳方式。任何想法如何改善?

實現:

我定義的自定義控制:

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

OnClick事件處理下面的方式(有點哈克,會很樂意學習如何更好地做到這一點):

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

Generic.xaml:

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

據我所知,你想避免在這種情況下的代碼。然而,沒有持久狀態,我們可以使用TriggerBinding來保持IsOpen爲真。你也可以調用命令,這個命令應該設置IsOpen爲真。但是,這需要在代碼隱藏中執行一些命令,這仍然是您想要避免的。

我只是覺得在這種情況下使用EventTrigger的,允許你啓動一個動畫,並與BooleanAnimationUsingKeyFrames,您可以輕鬆地將屬性設置爲truefalse。問題是Storyboard.Target應該下注。在Style的上下文中,我們不能使用Storyboard.TargetName,因爲Storyboard不是FrameworkElement,我們不能使用指定的ElementNameRelativeSource的綁定。綁定Storyboard.Target的唯一方法是使用與指定的Source綁定。通常這設置爲StaticResourceDynamicResource(或直接)。因此,您應該將Popup作爲具有指定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動畫。因此,要通過在代碼隱藏中的本地設置覆蓋它,您必須先移除動畫值(搜索如何覆蓋WPF中的動畫值)。

+0

謝謝King King的解決方案!我做此練習的主要原因是刪除代碼並改進xaml代碼的表達。所以,我真的想在附近保持超鏈接和彈出式功能。 – ZakiMa 2014-09-28 22:02:24