2016-05-10 16 views
1

Popup(以前に使用されていたToolTip btwを置き換えたもの)を含むアイテムには、DataTemplateという複合語があります。 1つのユースケース(他の3つのアパートメント)については、はItemsControl内で使用され、それ自体はScaleTransformを使用して25%から400%までスケーリングすることができます。 (新しい)PopUpも縮尺されていますが(ToolTipではありませんでした)、これは起こりたくありません。唯一の規模何らかの理由で継承されたトランスフォームを中和する方法は?

回転変換、伝播しているように見える変換されていません。

<StackPanel> 
    <Grid> 
     <Grid.LayoutTransform> 
      <ScaleTransform ScaleX="2" ScaleY="4"/> 
     </Grid.LayoutTransform> 
     <ToggleButton Name="btn1" Content="btn1" ToolTip="hello1" Padding="5"/> 
     <Popup IsOpen="{Binding IsChecked, ElementName=btn1}" StaysOpen="True"> 
      <TextBlock Background="Lime" Padding="10" Text="pop1!"/> 
     </Popup> 
    </Grid> 
    <Grid> 
     <Grid.LayoutTransform> 
      <RotateTransform Angle="25"/> 
     </Grid.LayoutTransform> 
     <ToggleButton Name="btn2" Content="btn2" ToolTip="hello2" Padding="5"/> 
     <Popup IsOpen="{Binding IsChecked, ElementName=btn2}" StaysOpen="True"> 
      <TextBlock Background="Lime" Padding="10" Text="pop2!"/> 
     </Popup> 
    </Grid> 
    <Grid> 
     <Grid.LayoutTransform> 
      <TransformGroup> 
       <RotateTransform Angle="25"/> 
       <ScaleTransform ScaleX="2" ScaleY="4"/> 
      </TransformGroup> 
     </Grid.LayoutTransform> 
     <ToggleButton Name="btn3" Content="btn3" ToolTip="hello3" Padding="5"/> 
     <Popup IsOpen="{Binding IsChecked, ElementName=btn3}" StaysOpen="True"> 
      <TextBlock Background="Lime" Padding="10" Text="pop3!"/> 
     </Popup> 
    </Grid> 
</StackPanel> 

答えて

2

オプション1:場所ポップアップLayoutTransform

の影響の外あなたは可能性があり変換されたグリッド外にPopupを定義し、を直接参照すると、次のようになります。

<Grid> 
    <Grid.LayoutTransform> 
     <TransformGroup> 
      <RotateTransform Angle="25"/> 
      <ScaleTransform ScaleX="2" ScaleY="4"/> 
     </TransformGroup> 
    </Grid.LayoutTransform> 
    <ToggleButton Name="btn3" Content="btn3" ToolTip="hello3" Padding="5"/> 
</Grid> 
<Popup IsOpen="{Binding IsChecked, ElementName=btn3}" StaysOpen="True" 
    PlacementTarget="{Binding ElementName=btn3}"> 
    <TextBlock Background="Lime" Padding="10" Text="pop3!"/> 
</Popup> 

オプション2:手動LayoutTransform

を反転それとも、あなたの現在のレイアウトを維持したい場合は、あなたがTransformationPopupに「逆転」を適用できます。

<Popup.LayoutTransform> 
    <ScaleTransform ScaleX="0.5" ScaleY="0.25"/> 
</Popup.LayoutTransform> 

しかし、その場合には、より良いオプションはBindingConverterを書くことです。それはあなたのためです。

オプション3:自動的にオプション4

public class TransformInverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, 
     object parameter, CultureInfo culture) 
    { 
     Transform transform = value as Transform; 
     if (transform == null) 
      return Transform.Identity; 
     return transform.Inverse; 
    } 

    public object ConvertBack(object value, Type targetType, 
     object parameter, CultureInfo culture) 
    { 
     return DependencyProperty.UnsetValue; 
    } 
} 
<Grid> 
    <Grid.LayoutTransform> 
     <TransformGroup> 
      <RotateTransform Angle="25"/> 
      <ScaleTransform ScaleX="2" ScaleY="4"/> 
     </TransformGroup> 
    </Grid.LayoutTransform> 
    <ToggleButton Name="btn3" Content="btn3" ToolTip="hello3" Padding="5"/> 
    <Popup IsOpen="{Binding IsChecked, ElementName=btn3}" StaysOpen="True" 
      LayoutTransform="{Binding 
      RelativeSource={RelativeSource AncestorType=Grid}, 
      Path=LayoutTransform, 
      Converter={StaticResource TransformInverter}}"> 
     <TextBlock Background="Lime" Padding="10" Text="pop3!"/> 
    </Popup> 
</Grid> 

LayoutTransformを反転:VisualTreeトラバースし、今、この1つは、ほとんどの場合、やり過ぎかもしれない

すべての変換を元に戻すが、ポップアップ自体にコンバータをバインドし、VisualTreeをトラバースし、すべてのLayoutTransformを保存し、逆Transfでキャンセルすることができますオマージュ。ただし、この方法では大きな欠点が1つあります。時間が経っても変換が変わることはできません。かいつまん:

public class TransformResetter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     FrameworkElement transformedElement = value as FrameworkElement; 
     if(transformedElement == null) 
      return DependencyProperty.UnsetValue; 

     Stack<Transform> transformations = new Stack<Transform>(); 

     FrameworkElement currentElement = transformedElement; 
     while (currentElement != null) 
     { 
      currentElement = VisualTreeHelper.GetParent(currentElement) as FrameworkElement; 
      if (currentElement != null) 
      { 
       if (currentElement.LayoutTransform != null) 
        transformations.Push(currentElement.LayoutTransform); 
      } 
     } 

     TransformGroup group = new TransformGroup(); 
     while (transformations.Count > 0) 
     { 
      group.Children.Add(transformations.Pop()); 
     } 

     return group.Inverse; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return DependencyProperty.UnsetValue; 
    } 
} 

そして、このようにそれを使用します。

<Popup IsOpen="{Binding IsChecked, ElementName=btn3}" StaysOpen="True" 
    LayoutTransform="{Binding 
     RelativeSource={RelativeSource Self}, 
     Converter={StaticResource TransformResetter}}"> 
    <TextBlock Background="Lime" Padding="10" Text="pop3!"/> 
</Popup> 

はオプション5:実行オプション4としてオープン

にLayoutTransformをリセットプロパティを取り付けて、基本的に同じ動作ポップアップが開くたびに:

public class PopupOptions 
{ 
    public static readonly DependencyProperty CancelTransformationsProperty = DependencyProperty.RegisterAttached(
     "CancelTransformations", typeof(bool), typeof(PopupOptions), new PropertyMetadata(default(bool), OnCancelTransformationsPropertyChanged)); 

    private static void OnCancelTransformationsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     Popup element = (Popup)d; 
     if ((bool)e.NewValue) 
     { 
      element.Opened += PopupChanged; 
      RefreshTransform(element); 
     } 
     else 
     { 
      element.Opened -= PopupChanged; 
     } 
    } 

    private static void PopupChanged(object sender, EventArgs eventArgs) 
    { 
     RefreshTransform(sender as FrameworkElement); 
    } 

    private static void RefreshTransform(FrameworkElement transformedElement) 
    { 
     if (transformedElement == null) 
      return; 

     Stack<Transform> transformations = new Stack<Transform>(); 

     FrameworkElement currentElement = transformedElement; 
     while (currentElement != null) 
     { 
      currentElement = VisualTreeHelper.GetParent(currentElement) as FrameworkElement; 
      if (currentElement == null) continue; 

      if (currentElement.LayoutTransform != null) 
       if (!currentElement.LayoutTransform.Value.IsIdentity) 
        transformations.Push(currentElement.LayoutTransform); 
     } 

     TransformGroup transformGroup = new TransformGroup(); 
     while (transformations.Count > 0) 
     { 
      transformGroup.Children.Add(transformations.Pop()); 
     } 

     Debug.WriteLine(transformGroup.Children[0].Value); 

     transformedElement.LayoutTransform = (Transform)transformGroup.Inverse; 
    } 

    public static void SetCancelTransformations(DependencyObject element, bool value) 
    { 
     if (!(element is Popup)) 
      throw new Exception("Nope!"); 

     element.SetValue(CancelTransformationsProperty, value); 
    } 

    public static bool GetCancelTransformations(DependencyObject element) 
    { 
     return (bool) element.GetValue(CancelTransformationsProperty); 
    } 
} 

使用法:

<Popup IsOpen="{Binding IsChecked, ElementName=btn3}" StaysOpen="True" 
    yourNameSpace:PopupOptions.CancelTransformations="True"> 
    <TextBlock Background="Lime" Padding="10" Text="pop3!"/> 
</Popup> 

背景情報

AllowsTransparencyfalseあるのでRotateTransformが適用されない理由はあります。これがなければ、ポップアップは四角いままでなければなりません。 trueに設定すると、回転も適用されます。

+0

「変換」について知っていれば、3つのオプションのいずれかを使用できます。しかし、DataTemplateはアプリケーションでグローバルに使用されているように、他のDataTemplateはそれをさらにContentPresenter内で使用して、さらに複雑なDataTemplatesを構築します。そして、そのようなDataTemplateは、最終的に、 'ItemsPanel'にScaleTransformが適用されたListBox内に配置されます(これは、寿命が限られた外部ウィンドウで発生します)。 – springy76

+0

ありがとうございました。別のオプションを追加しました。これでアイデアがなくなりましたので、これが役に立ちますようお願いいたします。 –

+0

オプション5は有望です。 BTW:オプション3は、バインディングパスを 'Inverse'プロパティに拡張するだけでコンバーターなしで行うことができます:' Path = LayoutTransform.Inverse' – springy76

関連する問題