2017-02-21 4 views
0

Я получил следующий Xamarin.Forms TemplatedView:Не удается получить InputTransparent работать на пользовательский элемент управления поповер

using System; 
using System.Threading.Tasks; 
using System.Windows.Input; 
using Xamarin.Forms; 

namespace STM.Framework.Controls 
{ 
    [ContentProperty(nameof(Content))] 
    public class PopOverLayout : TemplatedView 
    { 
     public PopOverLayout() 
     { 
     } 

     #region BoxViewTapCommand 

     public static BindableProperty BoxViewTapCommandProperty = BindableProperty.Create(nameof(BoxViewTapCommand), typeof(ICommand), typeof(PopOverLayout), default(ICommand), defaultValueCreator: BoxViewTapCommandCreator); 

     private static object BoxViewTapCommandCreator(BindableObject bindable) 
     { 
      return new Command(p => BoxViewTappedExecute(bindable as PopOverLayout, p)); 
     } 

     private static void BoxViewTappedExecute(PopOverLayout bindable, object parameter) 
     { 
      bindable.IsOverlayVisible = !bindable.IsOverlayVisible; 
      if (!bindable.IsOverlayVisible) 
      { 
       bindable.OverlayContent.InputTransparent = true; 
      } 
     } 

     public ICommand BoxViewTapCommand 
     { 
      get { return (ICommand) GetValue(BoxViewTapCommandProperty); } 
      set { SetValue(BoxViewTapCommandProperty, value); } 
     } 

     #endregion BoxViewTapCommand 

     #region OverlayContent 

     public static BindableProperty OverlayContentProperty = BindableProperty.Create(nameof(OverlayContent), typeof(VisualElement), typeof(PopOverLayout), default(VisualElement)); 

     public VisualElement OverlayContent 
     { 
      get { return (VisualElement) GetValue(OverlayContentProperty); } 
      set { SetValue(OverlayContentProperty, value); } 
     } 

     #endregion OverlayContent 

     #region Content 

     public static BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(VisualElement), typeof(PopOverLayout), default(VisualElement)); 

     public VisualElement Content 
     { 
      get { return (VisualElement) GetValue(ContentProperty); } 
      set { SetValue(ContentProperty, value); } 
     } 

     #endregion Content 

     #region IsOverlayVisible 

     public static BindableProperty IsOverlayVisibleProperty = BindableProperty.Create(nameof(IsOverlayVisible), typeof(bool), typeof(PopOverLayout), default(bool)); 

     public bool IsOverlayVisible 
     { 
      get { return (bool) GetValue(IsOverlayVisibleProperty); } 
      set { SetValue(IsOverlayVisibleProperty, value); } 
     } 

     #endregion IsOverlayVisible 
    } 
} 

App.xaml:

<Style TargetType="{x:Type controls:PopOverLayout}"> 
      <Setter Property="BackgroundColor" Value="#88000000" /> 
      <Setter Property="IsOverlayVisible" Value="False" /> 
      <Setter Property="ControlTemplate"> 
       <Setter.Value> 
        <ControlTemplate> 
         <Grid BackgroundColor="{TemplateBinding BackgroundColor}" > 
          <Grid.RowDefinitions> 
           <RowDefinition> 
            <RowDefinition.Height> 
             <OnIdiom x:TypeArguments="GridLength" Phone="0" Tablet="50" /> 
            </RowDefinition.Height> 
           </RowDefinition> 
           <RowDefinition Height="*" /> 
           <RowDefinition> 
            <RowDefinition.Height> 
             <OnIdiom x:TypeArguments="GridLength" Phone="0" Tablet="50" /> 
            </RowDefinition.Height> 
           </RowDefinition> 
          </Grid.RowDefinitions> 

          <Grid.ColumnDefinitions> 
           <ColumnDefinition> 
            <ColumnDefinition.Width> 
             <OnIdiom x:TypeArguments="GridLength" Phone="0" Tablet="50" /> 
            </ColumnDefinition.Width> 
           </ColumnDefinition> 
           <ColumnDefinition Width="*" /> 
           <ColumnDefinition> 
            <ColumnDefinition.Width> 
             <OnIdiom x:TypeArguments="GridLength" Phone="0" Tablet="50" /> 
            </ColumnDefinition.Width> 
           </ColumnDefinition> 
          </Grid.ColumnDefinitions> 
          <controls:EnhancedContentPresenter Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Grid.ColumnSpan="3" 
                   Content="{TemplateBinding Content}" /> 
          <BoxView Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Grid.ColumnSpan="3" 
            InputTransparent="{TemplateBinding IsOverlayVisible, Converter={StaticResource BooleanInversionConverter}, Mode=OneWay}" 
            IsVisible="{TemplateBinding IsOverlayVisible}" 
            BackgroundColor="{TemplateBinding BackgroundColor}"> 
           <BoxView.GestureRecognizers> 
            <TapGestureRecognizer Command="{TemplateBinding BoxViewTapCommand}"></TapGestureRecognizer> 
           </BoxView.GestureRecognizers> 
          </BoxView> 
          <controls:EnhancedContentPresenter Grid.Row="1" Grid.Column="1" Content="{TemplateBinding OverlayContent}" 
            InputTransparent="{TemplateBinding IsOverlayVisible, Converter={StaticResource BooleanInversionConverter}, Mode=OneWay}" 
            IsVisible="{TemplateBinding IsOverlayVisible}" /> 
         </Grid> 
        </ControlTemplate> 
       </Setter.Value> 
      </Setter> 
     </Style> 

Преобразователь:

public class BooleanInversionConverter : IValueConverter 
    { 
     public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      if (targetType != typeof(bool)) 
       throw new NotSupportedException(); 
      if (value.GetType() != typeof(bool)) 
       throw new NotSupportedException(); 
      var casted = (bool)value; 
      return !casted; 
     } 

     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
     { 
      if (targetType != typeof(bool)) 
       throw new NotSupportedException(); 
      if (value.GetType() != typeof(bool)) 
       throw new NotSupportedException(); 
      var casted = (bool)value; 
      return !casted; 
     } 
    } 

Контент-центр:

public class EnhancedContentPresenter : ContentPresenter 
{ 
    protected override void OnBindingContextChanged() 
    { 
     base.OnBindingContextChanged(); 
     if (BindingContext != null && this.Content != null) 
      SetInheritedBindingContext(this.Content, BindingContext); 
    } 
} 

Из-за природы элемента управления довольно очевидно, что я пытаюсь сделать, я думаю: если наложение скрыто, я не хочу, чтобы наложение захватывало события (или другие), а вместо этого вел себя так, как будто даже нет.

Однако я не могу заставить эту работу работать, потому что что-то продолжает захватывать события касания, даже если наложение скрыто, а InputTransparent - true.

Неужели эта проблема звонит кому-нибудь?

+0

Вы уверены, что шаблон связывания работает? Я думал, что нет. – Daniel

+0

@ Daniel В соответствии с отладкой он работает, да – Dbl

ответ

0

Я не уверен, является ли что-то еще не так с templatedView (потому что они уверены, что не хватает много возможностей WPF), но делать это, как это работает просто отлично:

[ContentProperty(nameof(Content))] 
public class PopOverLayout : RelativeLayout 
{ 
    #region OverlayContent 

    public static BindableProperty OverlayContentProperty = BindableProperty.Create(nameof(OverlayContent), typeof(View), typeof(PopOverLayout), default(View), propertyChanged: OverlayContentChanged); 

    private static void OverlayContentChanged(BindableObject bindable, object oldValue, object newValue) 
    { 
     var layout = bindable as PopOverLayout; 
     if (layout == null) 
      return; 

     layout.UpdateOverlayContent(); 
    } 

    public View OverlayContent 
    { 
     get { return (View) GetValue(OverlayContentProperty); } 
     set { SetValue(OverlayContentProperty, value); } 
    } 

    #endregion OverlayContent 

    #region Content 

    public static BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(PopOverLayout), default(View), propertyChanged: ContentChanged); 

    private static void ContentChanged(BindableObject bindable, object oldvalue, object newvalue) 
    { 
     var layout = bindable as PopOverLayout; 
     if (layout == null) 
      return; 

     layout.UpdateDisplayContent(); 
    } 

    public View Content 
    { 
     get { return (View) GetValue(ContentProperty); } 
     set { SetValue(ContentProperty, value); } 
    } 

    #endregion Content 

    #region IsOverlayVisible 

    public static BindableProperty IsOverlayVisibleProperty = BindableProperty.Create(nameof(IsOverlayVisible), typeof(bool), typeof(PopOverLayout), default(bool), propertyChanged: IsOverlayVisibleChanged); 

    private static void IsOverlayVisibleChanged(BindableObject bindable, object oldvalue, object newvalue) 
    { 
     var layout = bindable as PopOverLayout; 
     if (layout == null) 
      return; 

     bool newState = (bool) newvalue; 
     if (newState) 
     { 
      layout.ShowPopup(); 
     } 
     else 
     { 
      layout.HidePopup(); 
     } 
    } 

    public bool IsOverlayVisible 
    { 
     get { return (bool) GetValue(IsOverlayVisibleProperty); } 
     set { SetValue(IsOverlayVisibleProperty, value); } 
    } 

    #endregion IsOverlayVisible 

    protected override void OnParentSet() 
    { 
     base.OnParentSet(); 
     UpdateDisplayContent(); 
     UpdateOverlayContent(); 
    } 

    private View content; 
    private RelativeLayout popup; 

    private void UpdateDisplayContent() 
    { 
     if (content != null) 
      this.Children.Remove(content); 

     if (Content != null) 
     { 
      content = Content; 
      this.Children.Add(content, 
       Constraint.Constant(0), 
       Constraint.Constant(0), 
       Constraint.RelativeToParent(layout => layout.Width), 
       Constraint.RelativeToParent(layout => layout.Height)); 

      Content.InputTransparent = IsOverlayVisible; 
     } 
    } 

    private void UpdateOverlayContent() 
    { 
     if (popup != null) 
      this.Children.Remove(popup); 

     if (OverlayContent != null && IsOverlayVisible) 
     { 
      ShowPopup(); 
     } 
    } 

    private void HidePopup() 
    { 
     if (popup != null) 
      this.Children.Remove(popup); 

     OverlayContent.InputTransparent = true; 
     Content.InputTransparent = false; 
    } 

    private void ShowPopup() 
    { 
     if (popup != null) 
      this.Children.Remove(popup); 

     popup = new RelativeLayout(); 
     popup.GestureRecognizers.Add(new TapGestureRecognizer() {Command = new Command(PopUpTapped)}); 
     popup.BackgroundColor = BackgroundColor; 

     this.Children.Add(popup, 
      Constraint.Constant(0), 
      Constraint.Constant(0), 
      Constraint.RelativeToParent(layout => layout.Width), 
      Constraint.RelativeToParent(layout => layout.Height)); 

     popup.Children.Add(OverlayContent, 
      Constraint.RelativeToParent(layout => layout.X + 20), 
      Constraint.RelativeToParent(layout => layout.Y + 20), 
      Constraint.RelativeToParent(layout => layout.Width - 40), 
      Constraint.RelativeToParent(layout => layout.Height - 40)); 

     OverlayContent.InputTransparent = false; 
     Content.InputTransparent = true; 
    } 

    private void PopUpTapped(object o) 
    { 
     this.IsOverlayVisible = !IsOverlayVisible; 
    } 
} 
Смежные вопросы