2016-11-01 2 views
0

주제로 언급했듯이. 응용 프로그램의 모든 버튼에 대해 하나의 팝업 만 사용하고 싶습니다. 원하는 것을 얻는 방법을 모르겠습니다. 여기 내 창 모습입니다 같은 :모든 버튼에 대한 하나의 팝업

enter image description here

정보 1 :

enter image description here

정보 2 :

enter image description here

,536,

잘못된 위치에 팝업이 나타나는 것을 볼 수 있습니다. PlacementTarget을 설정하여 팝업을 배치 할 수 있습니다. 그러나 각 팝업에는 배치 속성에 대해 다른 값이 있습니다. 문제가 있습니다. 다른 방법이 있습니다.

<StackPanel Orientation="Horizontal"> 
<!--Option 2: text and button--> 
<TextBlock Text="Option 2" 
    Margin="10" 
    VerticalAlignment="Center" /> 
    <Button x:Name="btnOption2" 
    Style="{StaticResource btnIcons}" 
    Background="#0063b1" 
    Width="30" 
    Height="30" 
    Margin="10,10,20,10" 
    Command="{Binding CmdShowInfo, Delay=1500}" 
    Tag="{StaticResource ic_ginfo}" /> 
</StackPanel> 

ContentControl을 스타일 :

<Style TargetType="{x:Type ContentControl}" 
x:Key="ContentInfoStyle"> 
<Setter Property="ContentTemplate"> 
    <Setter.Value> 
    <DataTemplate> 
    <Border Background="Green" 
     CornerRadius="3" 
     Padding="10,0,12,10"> 
    <StackPanel> 
     <Button HorizontalAlignment="Right" 
     Tag="{StaticResource ic_gclear}" 
     Style="{StaticResource btnIcons}" 
     Background="White" 
     Margin="10,5,12,5" 
     Command="{Binding DataContext.CmdCloseInfo}" 
     Height="24" /> 
     <ContentPresenter x:Name="content" 
      TextBlock.FontSize="14" 
      TextBlock.Foreground="White" 
      TextBlock.FontFamily="Arial" 
      Content="{TemplateBinding ContentControl.Content}" /> 
    </StackPanel> 
    </Border> 
    </DataTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 

버튼 아이콘 스타일 :

옵션 2

<StackPanel Orientation="Horizontal"> 
<!--Option 1: text and button--> 
<TextBlock Text="Option 1" 
    Margin="10" 
    VerticalAlignment="Center" /> 
<Popup x:Name="popInfo" 
    PlacementTarget="{Binding ElementName=btnInfoOption1}" 
    IsOpen="{Binding IsShowInfo1}"> 
    <ContentControl Style="{StaticResource ContentInfoStyle}"> 
    <TextBlock Text="{Binding InfoContent}" 
     TextWrapping="Wrap" 
     Foreground="White" 
     Width="340" 
     Padding="10" 
     Margin="30,0,30,5" 
     FontSize="15" /> 
    </ContentControl> 
</Popup> 

<Button x:Name="btnInfoOption1" 
    Style="{StaticResource btnIcons}" 
    Background="#0063b1" 
    Width="30" 
    Height="30" 
    Margin="10,10,20,10" 
    Command="{Binding CmdShowInfo, Delay=1500}" 
    Tag="{StaticResource ic_ginfo}" /> 
</StackPanel> 

팝업 : 여기

옵션 1 팝업입니다
<Style TargetType="Button" 
    x:Key="btnIcons">   
    <Setter Property="Template"> 
    <Setter.Value> 
    <ControlTemplate TargetType="{x:Type Button}"> 
     <Border x:Name="brd" Background="Transparent" 
     SnapsToDevicePixels="True"> 
     <VisualStateManager.VisualStateGroups> 
     <VisualStateGroup x:Name="CommonStates"> 
     <VisualState x:Name="Normal" /> 
     <VisualState x:Name="MouseOver" /> 
     <VisualState x:Name="Pressed" /> 
     </VisualStateGroup> 
     </VisualStateManager.VisualStateGroups> 
     <Path Stretch="Uniform" VerticalAlignment="Center" 
     Fill="{TemplateBinding Background}" 
     Data="{TemplateBinding Tag}" /> 
     </Border> 
    </ControlTemplate> 
    </Setter.Value> 
    </Setter> 
</Style> 

ViewModel.cs : 팝업의 내용 :

private string _InfoContent; 

public string InfoContent 
{ 
    get { return _InfoContent; } 
    set 
    { 
    if (value != _InfoContent) 
    { 
     _InfoContent = value; 
     OnRaise("InfoContent"); 
    } 
    } 
} 

옵션 2옵션 1의 팝업을 보여

private bool _IsShowInfo2; 

public bool IsShowInfo2 
{ 
    get { return _IsShowInfo2; } 
    set 
    { 
    if (value != _IsShowInfo2) 
    { 
     _IsShowInfo2 = value; 
     OnRaise("IsShowInfo2"); 
    } 
    } 
} 
//show the popup for option1 
private bool _IsShowInfo1; 

public bool IsShowInfo1 
{ 
    get { return _IsShowInfo1; } 
    set 
    { 
    if (value != _IsShowInfo1) 
    { 
     _IsShowInfo1 = value; 
     OnRaise("IsShowInfo1"); 
    } 
    } 
} 

버튼의 명령을

private ICommand _CmdShowInfo; 

public ICommand CmdShowInfo 
{ 
    get 
    { 
    _CmdShowInfo = _CmdShowInfo ?? new RelayCommand(x => this.ShowInfo(true, 1),() => true); 
    return _CmdShowInfo; 
    } 
} 

private ICommand _CmdShowInfo2; 

public ICommand CmdShowInfo2 
{ 
    get 
    { 
    _CmdShowInfo2 = _CmdShowInfo2 ?? new RelayCommand(x => this.ShowInfo(true, 0),() => true); 
    return _CmdShowInfo2; 
    } 
} 

private void ShowInfo(bool show = true, byte option = 0) 
{ 
    if (option == 0) 
    { 
    this.InfoContent = "Option 1..."; 
    } 
    else if (option == 1) 
    { 
    this.InfoContent = "Option 2..."; 
    } 
    this.IsShowInfo1 = show; 
} 
+0

"옵션 2의 팝업"은 팝업이 아닙니다. 당신이 원하는 것을 확신 할 수는 없지만, 단지 하나의'Popup' 엘리먼트를 갖고 그것에 다른 컨텐트를 보여 주기만을 원한다면'HeaderContext' 스타일을'ContentTemplate' 스타일로 씁니다. 버튼의 내용이고'Popup'의'Content'입니다. –

+0

예, 어렵다는 것을 알고 있습니다. HeaderedContentControl 대 팝업에 대해 자세히 설명해 주시겠습니까? @EdPlunkett – Jandy

+0

ic_gclear 및 ic_ginfo의 정의를 볼 수 있습니까? –

답변

1

처음 생각한 스타일은 HeaderedContentControl 이었지만, 아이콘 채우기 색상과 아이콘 데이터가 있습니다. 그런 경우 첨부 된 속성을 추가해야했습니다. 일단 거기에 가면 사용자 정의 컨트롤을 작성할 수 있습니다. IconPopupButton

종속성 속성은 종속성 속성과 같은 바인딩 할 수 있습니다

<hec:IconPopupButton 
    IsOpen="{Binding IsShowInfo1}" 
    IconFill="YellowGreen" 
    Content="Another Test Popup" 
    IconData="M -10,-10 M 0,3 L 17,20 L 20,17 L 3,0 Z M 0,0 L 0,20 L 20,20 L 20,0 Z" 
    /> 

당신의 PopupStyleContentControl에 적용되는 매개 변수화 다른 종속성 속성을 추가하려면

. 하지만 템플릿을 적용한 부모의 경우 을 IsOpen에 바인딩해야하므로 생각을 좀해야합니다. 아마도 팝업 버튼의 IsOpen에 바인딩 된 viewmodel 속성에 바인딩 할 수 있습니다. 항상 방법이 있습니다.

그래서 여기 있습니다. 종속성 속성을 만드는 스 니펫 (snippet)을 사용하면 공백 채우기 연습 만 할 수 있습니다. 눈을 맞추는 것보다 훨씬 적습니다.

<Window 
    x:Class="HeaderedPopupTest.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:local="clr-namespace:HeaderedPopupTest" 
    xmlns:hec="clr-namespace:HollowEarth.Controls" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="350" Width="525" 
    > 
    <Window.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="Themes\Shared.xaml" /> 
      </ResourceDictionary.MergedDictionaries> 

      <Style 
       x:Key="InfoPopupButton" 
       TargetType="hec:IconPopupButton" 
       BasedOn="{StaticResource {x:Type hec:IconPopupButton}}" 
       > 
       <Setter Property="IconFill" Value="DeepSkyBlue" /> 
       <Setter Property="IconData" Value="{StaticResource ic_ginfo}" /> 
      </Style> 
     </ResourceDictionary> 
    </Window.Resources> 

    <Grid> 
     <StackPanel 
      Orientation="Vertical" 
      HorizontalAlignment="Left" 
      > 
      <hec:IconPopupButton 
       Style="{StaticResource InfoPopupButton}" 
       Content="This is a test popup" 
       ToolTip="Test Popup Tooltip" 
       /> 
      <hec:IconPopupButton 
       IconFill="YellowGreen" 
       Content="Another Test Popup" 
       IconData="M -10,-10 M 0,3 L 17,20 L 20,17 L 3,0 Z M 0,0 L 0,20 L 20,20 L 20,0 Z" 
       /> 
      <hec:IconPopupButton 
       IconFill="DarkRed" 
       Content="Missing IconData behavior example" 
       /> 
     </StackPanel> 
    </Grid> 
</Window> 
,536,913,632 :

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:HeaderedPopupTest.Themes" 
    > 
    <Geometry x:Key="ic_gclear">M56,4 52,0 28,24 4,0 0,4 24,28 0,52 4,56 28,32 52,56 56,52 32,28Z</Geometry> 
    <Geometry x:Key="ic_ginfo">M31,0C13.879,0,0,13.879,0,31s13.879,31,31,31s31-13.879,31-31S48.121,0,31,0z M34,46h-6V27.969h6V46z M34,21.969h-6V16h6V21.969z</Geometry> 

    <Style TargetType="ButtonBase" x:Key="btnIcons"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type ButtonBase}"> 
        <Border x:Name="brd" Background="Transparent" SnapsToDevicePixels="True"> 
         <VisualStateManager.VisualStateGroups> 
          <VisualStateGroup x:Name="CommonStates"> 
           <VisualState x:Name="Normal" /> 
           <VisualState x:Name="MouseOver" /> 
           <VisualState x:Name="Pressed" /> 
          </VisualStateGroup> 
         </VisualStateManager.VisualStateGroups> 
         <Grid> 
          <Path 
           x:Name="Path" 
           Stretch="Uniform" 
           VerticalAlignment="Center" 
           Fill="{TemplateBinding Background}" 
           Data="{TemplateBinding Tag}" 
           /> 
          <TextBlock 
           x:Name="MissingIconData" 
           Visibility="Collapsed" 
           Text="?" 
           FontWeight="Bold" 
           FontSize="30" 
           ToolTip="IconData (Tag) not set" 
           HorizontalAlignment="Center" 
           VerticalAlignment="Center" 
           /> 
         </Grid> 
        </Border> 
        <ControlTemplate.Triggers> 
         <Trigger Property="Tag" Value="{x:Null}"> 
          <Setter TargetName="MissingIconData" Property="Visibility" Value="Visible" /> 
         </Trigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 

</ResourceDictionary> 

테마

<ResourceDictionary 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:HeaderedPopupTest.Themes" 
    xmlns:hec="clr-namespace:HollowEarth.Controls" 
    > 

    <ResourceDictionary.MergedDictionaries> 
     <!-- Change HeaderedPopupTest to the name of your own assembly --> 
     <ResourceDictionary Source="/HeaderedPopupTest;component/Themes/Shared.xaml" /> 
    </ResourceDictionary.MergedDictionaries> 

    <Style TargetType="hec:IconPopupButton"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="hec:IconPopupButton"> 
        <Grid x:Name="Grid"> 
         <ToggleButton 
          x:Name="OpenButton" 
          Style="{StaticResource btnIcons}" 
          Background="{TemplateBinding IconFill}" 
          Tag="{TemplateBinding IconData}" 
          IsChecked="{Binding IsOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" 
          ToolTip="{TemplateBinding ToolTip}" 
          /> 
         <Popup 
          x:Name="Popup" 
          StaysOpen="{Binding StaysOpen, RelativeSource={RelativeSource TemplatedParent}}" 
          IsOpen="{Binding IsOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" 
          PlacementTarget="{Binding ElementName=ToggleButton}" 
          Placement="{TemplateBinding Placement}" 
          > 
          <Border 
           Background="Green" 
           CornerRadius="3" 
           Padding="10,0,12,10"> 
           <StackPanel> 
            <ToggleButton 
             HorizontalAlignment="Right" 
             Tag="{StaticResource ic_gclear}" 
             Style="{StaticResource btnIcons}" 
             Background="White" 
             Margin="10,5,12,5" 
             IsChecked="{Binding IsOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}" 
             Height="24" 
             /> 
            <ContentPresenter 
             x:Name="content" 
             TextBlock.FontSize="14" 
             TextBlock.Foreground="White" 
             TextBlock.FontFamily="Arial" 
             Content="{TemplateBinding Content}" 
             /> 
           </StackPanel> 
          </Border> 
         </Popup> 
        </Grid> 
        <ControlTemplate.Triggers> 
         <MultiTrigger> 
          <MultiTrigger.Conditions> 
           <!-- 
           I don't understand this: If I use the templated parent's IsOpen, 
           the effect is as if it were never true. 
           --> 
           <Condition SourceName="Popup" Property="IsOpen" Value="True" /> 
           <Condition Property="StaysOpen" Value="False" /> 
          </MultiTrigger.Conditions> 
          <!-- 
          If StaysOpen is false and the button is enabled while the popup is open, 
          then clicking on it will cause the popup to flicker rather than close. 
          --> 
          <Setter TargetName="OpenButton" Property="IsEnabled" Value="False" /> 
         </MultiTrigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

MainWindow.xaml의 사용 예 generic.xaml을 \ Shared.xaml \

IconPopupButton.cs

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Controls.Primitives; 
using System.Windows.Media; 

namespace HollowEarth.Controls 
{ 
    public class IconPopupButton : ContentControl 
    { 
     static IconPopupButton() 
     { 
      DefaultStyleKeyProperty.OverrideMetadata(typeof(IconPopupButton), new FrameworkPropertyMetadata(typeof(IconPopupButton))); 
     } 

     #region IconData Property 
     public Geometry IconData 
     { 
      get { return (Geometry)GetValue(IconDataProperty); } 
      set { SetValue(IconDataProperty, value); } 
     } 

     public static readonly DependencyProperty IconDataProperty = 
      DependencyProperty.Register("IconData", typeof(Geometry), typeof(IconPopupButton), 
       new PropertyMetadata(null)); 
     #endregion IconData Property 

     #region IconFill Property 
     public Brush IconFill 
     { 
      get { return (Brush)GetValue(IconFillProperty); } 
      set { SetValue(IconFillProperty, value); } 
     } 

     public static readonly DependencyProperty IconFillProperty = 
      DependencyProperty.Register("IconFill", typeof(Brush), typeof(IconPopupButton), 
       new PropertyMetadata(SystemColors.ControlTextBrush)); 
     #endregion IconFill Property 

     #region IsOpen Property 
     public bool IsOpen 
     { 
      get { return (bool)GetValue(IsOpenProperty); } 
      set { SetValue(IsOpenProperty, value); } 
     } 

     public static readonly DependencyProperty IsOpenProperty = 
      DependencyProperty.Register("IsOpen", typeof(bool), typeof(IconPopupButton), 
       new PropertyMetadata(false)); 
     #endregion IsOpen Property 

     #region StaysOpen Property 
     public bool StaysOpen 
     { 
      get { return (bool)GetValue(StaysOpenProperty); } 
      set { SetValue(StaysOpenProperty, value); } 
     } 

     public static readonly DependencyProperty StaysOpenProperty = 
      DependencyProperty.Register("StaysOpen", typeof(bool), typeof(IconPopupButton), 
       new PropertyMetadata(false)); 
     #endregion StaysOpen Property 

     #region Placement Property 
     public PlacementMode Placement 
     { 
      get { return (PlacementMode)GetValue(PlacementProperty); } 
      set { SetValue(PlacementProperty, value); } 
     } 

     public static readonly DependencyProperty PlacementProperty = 
      DependencyProperty.Register("Placement", typeof(PlacementMode), typeof(IconPopupButton), 
       new PropertyMetadata(PlacementMode.Right)); 
     #endregion Placement Property 
    } 
} 

테마 10

버튼이 ToggleButton으로 변경되었습니다. 이것은 IsOpen 속성까지 편리하게 배선 할 수 있습니다. ToggleButton을 사용하면 IsChecked을 바인딩하면 완료됩니다. 명령이 필요 없습니다. 그 중 하나의 부작용 StaysOpenfalse 경우 사용자가 Popup위한 열기 버튼을 클릭하면, 다음에, 포커스 변경 버튼을 마우스 메시지가 도착 후 상기 버튼을 선택하거나 선택 취소 Popup, 및 를 폐쇄이다. 그러면 버튼이 팝업을 다시 엽니 다. 이것은 사용자의 관점에서 보면 기괴한 동작이므로 팝업이 열려 있고 StaysOpen이 false 일 때 버튼을 비활성화하는 트리거를 추가합니다. StaysOpen이 true이면 포커스 변경으로 Popup이 닫히지 않으므로이 경우 버튼을 활성화해야합니다.

스타일을 ButtonBase으로 변경하여 ButtonToggleButton과 동일하게 작동합니다.

+0

나는 그것이 무엇인지 모르겠다. 그것은 사용자 정의 컨트롤처럼 보입니다 .ToggleButton 및 TextBox Collapsed.lol. – Jandy

+0

@Jandy 나에게 무엇을 말하려고하는지 전혀 모르겠다. –

+0

창이 비활성화되면 사라집니다. 명령이 필요 없습니다. 팝업 만 표시합니다. 놀라운 일입니다! scrollviewer에 넣으려고합니다. 더 많은 메모리가 필요하지 않기를 바랍니다. 감사합니다. @EdPlunkett – Jandy

관련 문제