オプション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
を反転それとも、あなたの現在のレイアウトを維持したい場合は、あなたがTransformation
Popup
に「逆転」を適用できます。
<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>
背景情報
AllowsTransparency
がfalse
あるのでRotateTransform
が適用されない理由はあります。これがなければ、ポップアップは四角いままでなければなりません。 true
に設定すると、回転も適用されます。
「変換」について知っていれば、3つのオプションのいずれかを使用できます。しかし、DataTemplateはアプリケーションでグローバルに使用されているように、他のDataTemplateはそれをさらにContentPresenter内で使用して、さらに複雑なDataTemplatesを構築します。そして、そのようなDataTemplateは、最終的に、 'ItemsPanel'にScaleTransformが適用されたListBox内に配置されます(これは、寿命が限られた外部ウィンドウで発生します)。 – springy76
ありがとうございました。別のオプションを追加しました。これでアイデアがなくなりましたので、これが役に立ちますようお願いいたします。 –
オプション5は有望です。 BTW:オプション3は、バインディングパスを 'Inverse'プロパティに拡張するだけでコンバーターなしで行うことができます:' Path = LayoutTransform.Inverse' – springy76