2016-09-22 3 views
0

У меня есть Flyout со вспомогательным помощником, который помогает связать с родительским элементом, который определяет его свойство PlacementTarget.Связывание с другим ElementName в Windows 10 UWP с использованием StateTriggers

линия, что я пытаюсь настроить это

helpers:FlyoutHelper.Parent="{Binding ElementName=appBarDelete}" 

Он отлично работает на рабочем столе, но на Windows Mobile, я хочу, чтобы привязать к другому ElementName. Есть ли способ создать нечто вроде условного связывания в зависимости от того, работает ли он на мобильном или рабочем столе?

Я попытался привязать свойство string в моей модели 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); 
    } 
} 

Update

мне удалось установить 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

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 обеспечивается Template 10 - see on GitHub. С помощью этого кода вы можете упростить код до:

flyOut.SetValue(FlyoutHelper.ParentProperty, 
    DeviceUtils.CurrentDeviceFamily == DeviceFamilies.Mobile ? 
     theElementOnMobile : appBarDelete); 
+0

Спасибо @MZetko. Я понял, что это возможно. Однако я немного изменил вопрос. Я хочу сделать это на 'StateTriggers'. См. Обновленный вопрос. Благодарю. – PutraKg

+0

Я пробовал ваше предложение, но получаю сообщение «DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION» с сообщением «Катастрофический сбой». Я пытаюсь создать публичную собственность «Parent». 'public FrameworkElement Parent { get {return (FrameworkElement) GetValue (ParentProperty); } set {SetValue (ParentProperty, значение); } } 'Но VisualStudio жаловался, что GetValue и SetValue не существуют в текущем контексте. – PutraKg

+0

Возможно, мне нужно создать 'UserControl', который наследует' Flyout'? – PutraKg

Смежные вопросы