我有一个带有助手的Flyout
来帮助绑定到确定其PlacementTarget
属性的父元素。
我想调整的行是
helpers:FlyoutHelper.Parent="{Binding ElementName=appBarDelete}"
它在桌面上工作正常,但在Windows Mobile上,我想绑定到不同的ElementName
。有没有办法创建条件绑定之类的东西,具体取决于它是在Mobile还是Desktop上运行?
我已经尝试绑定到我的ViewModel中的字符串属性,但是帮助器因为期望FrameworkElement而抱怨。我认为ElementName
可以是任何字符串,也许有一个内部转换器将此字符串转换为FrameworkElement
?
有什么想法吗?
<AppBarButton x:Name="menuZoom" Label="Thumbnail Size" >
<FlyoutBase.AttachedFlyout>
<Flyout x:Name="flyOut" helpers:FlyoutHelper.IsOpen="{Binding IsOpen, Mode=TwoWay}" helpers:FlyoutHelper.Parent="{Binding ElementName=appBarDelete}">
<StackPanel Width="240">
<TextBlock Text="Desired Size"/>
<Slider Minimum="50" Maximum="500" Value="{Binding ImageDesiredWidth, Mode=TwoWay}" />
<Button Content="OK" Command="{Binding CloseCommand}" HorizontalAlignment="Right" />
</StackPanel>
</Flyout>
</FlyoutBase.AttachedFlyout>
这是我的FloutHelper
班级
public static class FlyoutHelper
{
public static readonly DependencyProperty IsVisibleProperty =
DependencyProperty.RegisterAttached(
"IsOpen", typeof(bool), typeof(FlyoutHelper),
new PropertyMetadata(true, IsOpenChangedCallback));
public static readonly DependencyProperty ParentProperty =
DependencyProperty.RegisterAttached(
"Parent", typeof(FrameworkElement), typeof(FlyoutHelper), null);
public static void SetIsOpen(DependencyObject element, bool value)
{
element.SetValue(IsVisibleProperty, value);
}
public static bool GetIsOpen(DependencyObject element)
{
return (bool)element.GetValue(IsVisibleProperty);
}
private static async void IsOpenChangedCallback(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var fb = d as FlyoutBase;
if (fb == null)
return;
if ((bool)e.NewValue)
{
try
{
fb.Closed += flyout_Closed;
fb.ShowAt(GetParent(d));
}
catch (Exception msg)
{
var dialog = new MessageDialog(msg.Message);
await dialog.ShowAsync();
}
}
else
{
fb.Closed -= flyout_Closed;
fb.Hide();
}
}
private static void flyout_Closed(object sender, object e)
{
// When the flyout is closed, sets its IsOpen attached property to false.
SetIsOpen(sender as DependencyObject, false);
}
public static void SetParent(DependencyObject element, FrameworkElement value)
{
element.SetValue(ParentProperty, value);
}
public static FrameworkElement GetParent(DependencyObject element)
{
return (FrameworkElement)element.GetValue(ParentProperty);
}
}
更新
我已设法使用以下代码从后面的代码中设置Parent
属性。
private void setFlyoutParent()
{
if (DeviceTypeHelper.GetDeviceFormFactorType() == DeviceFormFactorType.Phone)
{
FlyoutHelper.SetParent(this.flyOut, this.appBarPath);
}
else
{
FlyoutHelper.SetParent(this.flyOut, this.appBarDelete);
}
}
工作正常,但我想使用VisualState.StateTriggers
并在MinWindowWidth
上设置属性
答案 0 :(得分:0)
在您更新问题时,也可以使用AdaptiveTrigger
来执行您需要的操作。由于FlyoutHelper.ParentProperty
是附加属性,因此您需要使用括号将其设置为:
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MaxWindowWidth="..." />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="flyOut.(helpers:FlyoutHelper.Parent)"
Value="{Binding ElementName=theElementOnMobile}" />
</VisualState.Setters>
</VisualState>
最简单的解决方案是在页面的代码隐藏中执行此操作。在构造函数中,在InitializeComponent
调用之后添加以下内容:
if ( AnalyticsInfo.VersionInfo.DeviceFamily.Contains( "Mobile" ) )
{
flyOut.SetValue( FlyoutHelper.ParentProperty, theElementOnMobile );
}
else
{
flyOut.SetValue( FlyoutHelper.ParentProperty, appBarDelete );
}
为了使其更清洁,您可以使用DeviceUtils
- see on GitHub提供的Template 10
。有了这个,您可以将代码简化为:
flyOut.SetValue( FlyoutHelper.ParentProperty,
DeviceUtils.CurrentDeviceFamily == DeviceFamilies.Mobile ?
theElementOnMobile : appBarDelete );