使用StateTriggers绑定到Windows 10 UWP上的其他ElementName

时间:2016-09-22 08:28:12

标签: xaml binding uwp windows-10-universal flyout

我有一个带有助手的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上设置属性

1 个答案:

答案 0 :(得分:0)

AdaptiveTrigger

在您更新问题时,也可以使用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 );