2008-12-11 17 views
54

मुझे दो नियंत्रण, टेक्स्टब्लॉक और पॉपअप मिला है। जब उपयोगकर्ता टेक्स्टब्लॉक पर (माउसडाउन) क्लिक करता है, तो मैं पॉपअप प्रदर्शित करना चाहता हूं। मुझे लगता है कि मैं पॉपअप पर इवेंट ट्रिगर के साथ ऐसा कर सकता हूं, लेकिन मैं इवेंट ट्रिगर में सेटर्स का उपयोग नहीं कर सकता, मैं केवल स्टोरीबोर्ड शुरू कर सकता हूं। मैं इसे XAML में सख्ती से करना चाहता हूं, क्योंकि दो नियंत्रण टेम्पलेट में हैं और मुझे नहीं पता कि मुझे कोड में पॉपअप कैसे मिलेगा।एक्सएएमएल मार्कअप का उपयोग करके, एक और नियंत्रण क्लिक होने पर एक WPF पॉपअप कैसे खोलें?

यह धारणात्मक मुझे क्या करना चाहते है, लेकिन नहीं है क्योंकि आप नहीं एक सेटर एक EventTrigger में (जैसे आप कर सकते हैं एक DataTrigger साथ) डाल सकते हैं कर सकते हैं:

<TextBlock x:Name="CCD">Some text</TextBlock> 

<Popup> 
    <Popup.Style> 
     <Style> 
      <Style.Triggers> 
       <EventTrigger SourceName="CCD" RoutedEvent="MouseDown"> 
        <Setter Property="Popup.IsOpen" Value="True" /> 
       </EventTrigger> 
      </Style.Triggers> 
     </Style> 
    </Popup.Style> 
... 

का सबसे अच्छा तरीका क्या है जब एक घटना एक अलग नियंत्रण पर होती है तो एक्सएएमएल में सख्ती से एक पॉपअप दिखाएं?

उत्तर

77

मैंने कुछ आसान किया, लेकिन यह काम करता है।

मैंने एक ठेठ टॉगल बटन का उपयोग किया, जिसे मैंने अपने नियंत्रण टेम्पलेट को बदलकर टेक्स्टब्लॉक के रूप में पुन: स्थापित किया। तब मैंने पॉपअप पर IsOpen संपत्ति पर ToggleButton पर Ischecked संपत्ति को बाध्य किया। पॉपअप में कुछ गुण हैं जैसे StaysOpen जो आपको समापन व्यवहार को संशोधित करने देता है।

निम्नलिखित xamlPad में काम करता है।

<ToggleButton x:Name="Btn" IsHitTestVisible="{Binding ElementName=Popup, Path=IsOpen, Mode=OneWay, Converter={local:BoolInverter}}"> 
    <TextBlock Text="Click here for popup!"/> 
</ToggleButton> 

<Popup IsOpen="{Binding IsChecked, ElementName=Btn}" x:Name="Popup" StaysOpen="False"> 
    <Border BorderBrush="Black" BorderThickness="1" Background="LightYellow"> 
     <CheckBox Content="This is a popup"/> 
    </Border> 
</Popup> 

"BoolInverter" में प्रयोग किया जाता है: सिवाय इसके कि पॉपअप स्वचालित रूप से बंद है जब आप पॉपअप (ToggleButton खुद सहित) के बाहर कहीं भी क्लिक करें

<StackPanel> 
    <ToggleButton Name="button"> 
    <ToggleButton.Template> 
     <ControlTemplate TargetType="ToggleButton"> 
     <TextBlock>Click Me Here!!</TextBlock> 
     </ControlTemplate>  
    </ToggleButton.Template> 
    </ToggleButton> 
    <Popup IsOpen="{Binding IsChecked, ElementName=button}" StaysOpen="False"> 
    <Border Background="LightYellow"> 
     <TextBlock>I'm the popup</TextBlock> 
    </Border> 
    </Popup> 
</StackPanel> 
+0

दिलचस्प दृष्टिकोण – viggity

+4

@ Qwertie का दृष्टिकोण यह भी देख के साथ Storyboard सामान की जगह सरल किया जा सकता - कि पॉपअप अपने आप बंद हो जाएगा इस से प्रेरित एक अधिक उपयोगी संस्करण alt-tab या पॉपअप –

8

मुझे इसके माउसडाउन हिस्से के साथ कुछ समस्याएं थीं, लेकिन यहां कुछ कोड है जो आपकी शुरुआत कर सकते हैं।

<Window x:Class="WpfApplication1.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="300" Width="300"> 
    <Grid> 
     <Control VerticalAlignment="Top"> 
      <Control.Template> 
       <ControlTemplate> 
        <StackPanel> 
        <TextBox x:Name="MyText"></TextBox> 
        <Popup x:Name="Popup" PopupAnimation="Fade" VerticalAlignment="Top"> 
         <Border Background="Red"> 
          <TextBlock>Test Popup Content</TextBlock> 
         </Border> 
        </Popup> 
        </StackPanel> 
        <ControlTemplate.Triggers> 
         <EventTrigger RoutedEvent="UIElement.MouseEnter" SourceName="MyText"> 
          <BeginStoryboard> 
           <Storyboard> 
            <BooleanAnimationUsingKeyFrames Storyboard.TargetName="Popup" Storyboard.TargetProperty="(Popup.IsOpen)"> 
             <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="True"/> 
            </BooleanAnimationUsingKeyFrames> 
           </Storyboard> 
          </BeginStoryboard> 
         </EventTrigger> 
         <EventTrigger RoutedEvent="UIElement.MouseLeave" SourceName="MyText"> 
          <BeginStoryboard> 
           <Storyboard> 
            <BooleanAnimationUsingKeyFrames Storyboard.TargetName="Popup" Storyboard.TargetProperty="(Popup.IsOpen)"> 
             <DiscreteBooleanKeyFrame KeyTime="00:00:00" Value="False"/> 
            </BooleanAnimationUsingKeyFrames> 
           </Storyboard> 
          </BeginStoryboard> 
         </EventTrigger> 
        </ControlTemplate.Triggers> 
       </ControlTemplate> 
      </Control.Template> 
     </Control> 
    </Grid> 
</Window> 
48

निम्नलिखित दृष्टिकोण, हेल्गे क्लेन रूप में ही है IsHitTestVisible बंधन ताकि जब आप ToggleButton फिर से क्लिक करें, पॉपअप बंद कर देता है:

public class BoolInverter : MarkupExtension, IValueConverter 
{ 
    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     return this; 
    } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value is bool) 
      return !(bool)value; 
     return value; 
    } 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return Convert(value, targetType, parameter, culture); 
    } 
} 

... जो एक में combining IValueConverter and MarkupExtension की आसान तकनीक दिखाता है।

मुझे इस तकनीक के साथ एक समस्या का पता चला: WPF एक ही समय में स्क्रीन पर दो पॉपअप होने पर छोटी है। विशेष रूप से, यदि आपका टॉगल बटन टूलबार में "ओवरफ़्लो पॉपअप" पर है, तो क्लिक करने के बाद दो पॉपअप खुल जाएंगे। फिर आप पाते हैं कि दूसरी पॉपअप (आपका पॉपअप) तब खुल जाएगा जब आप अपनी विंडो पर कहीं और क्लिक करेंगे। उस बिंदु पर, पॉपअप को बंद करना मुश्किल है। उपयोगकर्ता पॉपअप को बंद करने के लिए फिर से ToggleButton पर क्लिक नहीं कर सकता क्योंकि IsHitTestVisible गलत है क्योंकि पॉपअप खुला है! मेरे ऐप में मुझे इस समस्या को कम करने के लिए कुछ हैक्स का उपयोग करना पड़ा, जैसे मुख्य विंडो पर निम्न परीक्षण, जो कहते हैं (लुई ब्लैक की आवाज़ में) "यदि पॉपअप खुला है और उपयोगकर्ता पॉपअप के बाहर कहीं भी क्लिक करता है, 'friggin पॉपअप बंद ":।

PreviewMouseDown += (s, e) => 
{ 
    if (Popup.IsOpen) 
    { 
     Point p = e.GetPosition(Popup.Child); 
     if (!IsInRange(p.X, 0, ((FrameworkElement)Popup.Child).ActualWidth) || 
      !IsInRange(p.Y, 0, ((FrameworkElement)Popup.Child).ActualHeight)) 
      Popup.IsOpen = false; 
    } 
}; 
+1

के बाहर क्लिक करें यह बहुत अच्छा काम करता है - जिसमें किसी अन्य एप्लिकेशन पर alt-tabbing शामिल है या विंडो –

+1

में कहीं और क्लिक करना StaysOpen = "false" आउट-ऑफ-घटक ऑटो-क्लोज़ व्यवहार की कुंजी है। क्यों ओह यह सच क्यों है ?? –

+1

@ क्रिसडोलन मैं उन चीजों से बहुत परेशान हूं जो मूल रूप से हर यूएक्स सिद्धांत के खिलाफ जाते हैं जो मुझे पता है। इसलिए, मैं 'पॉपअप' के लिए एक निहित शैली बना देता हूं और 'StaysOpen = False' सहित डिफ़ॉल्ट को सेट करता हूं। – erodewald

0

एक और तरीका यह करने के लिए:

<Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true"> 
        <StackPanel> 
         <Image Source="{Binding ProductImage,RelativeSource={RelativeSource TemplatedParent}}" Stretch="Fill" Width="65" Height="85"/> 
         <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/> 
         <Button x:Name="myButton" Width="40" Height="10"> 
          <Popup Width="100" Height="70" IsOpen="{Binding ElementName=myButton,Path=IsMouseOver, Mode=OneWay}"> 
           <StackPanel Background="Yellow"> 
            <ItemsControl ItemsSource="{Binding Produkt.SubProducts}"/> 
           </StackPanel> 
          </Popup> 
         </Button> 
        </StackPanel> 
       </Border> 
8

कैसे के बारे में:

<Button x:Name="OpenPopup">Popup 
    <Button.Triggers> 
     <EventTrigger RoutedEvent="Button.Click"> 
      <EventTrigger.Actions> 
       <BeginStoryboard> 
        <Storyboard> 
         <BooleanAnimationUsingKeyFrames 
           Storyboard.TargetName="ContextPopup" 
           Storyboard.TargetProperty="IsOpen"> 
          <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" /> 
         </BooleanAnimationUsingKeyFrames> 
        </Storyboard> 
       </BeginStoryboard> 
      </EventTrigger.Actions> 
     </EventTrigger> 
    </Button.Triggers> 
</Button> 
<Popup x:Name="ContextPopup" 
     PlacementTarget="{Binding ElementName=OpenPopup}" 
     StaysOpen="False"> 
    <Label>Popupcontent...</Label> 
</Popup> 

कृपया ध्यान दें कि Popupreferecing है नाम सेऔर इसके विपरीत।तो दोनों पर Popup और Button दोनों की आवश्यकता है।

यह वास्तव में आगे एक कस्टम SetProperty EventTrigger कार्रवाई वर्णित in this SO Answer

संबंधित मुद्दे