【问题标题】:Forwarding events/commands when using Xamarin.Forms Custom Renderer使用 Xamarin.Forms 自定义渲染器时转发事件/命令
【发布时间】:2017-02-10 12:17:22
【问题描述】:

在我的 Xamarin.Forms 应用程序中,我希望自定义按钮的外观和感觉比允许的程度更高,因此我使用自定义渲染器将 Windows Phone 8.1 上 Xamarin.Forms 中的默认控件替换为我自己的按钮控件.

我的控件只是扩展了 Button,稍后会添加额外的属性。

public class ButtonControl : Button {}

我在 Windows Phone 8.1 上的自定义渲染器:

public class ButtonControlRenderer : ViewRenderer<ButtonControl, Button>
  {
    protected override void OnElementChanged(ElementChangedEventArgs<ButtonControl> e)
    {
      base.OnElementChanged(e);

      if (e.OldElement != null || Element == null)
        return;

      var button = new Button
      {
        Style = Application.Current.Resources["ButtonWithTilt"] as Style,
        Content = Element.Text,
        IsEnabled = Element.IsEnabled
      };

      Element.BackgroundColor = Color.Transparent;

      SetNativeControl(button);
    }
  }

还有,我如何使用 Xamarin.Forms XAML 文件中的控件:

<StackLayout VerticalOptions="Center"
                         HorizontalOptions="Fill"
                         Margin="24,12,24,0">
              <controls:ButtonControl Text="{res:Translate LoginPageButtonText}"
                      TextColor="{x:Static const:Colours.OverlayColor}"
                      BackgroundColor="{x:Static const:Colours.PrimaryColor}"
                      BorderWidth="0"
                      Margin="0,24,0,0"
                      HeightRequest="50"
                      IsEnabled="{Binding LoginValid}"
                      Command="{Binding LoginCommand}"
                      StyleId="{x:Static const:StyleIds.LoginPageButton}"/>
            </StackLayout>

当我替换按钮时,我的命令不能开箱即用,我必须将以下内容添加到 OnElementChanged 中,以便在单击我的新按钮时执行命令:

button.Tapped += delegate
      {
        Element.Command.Execute(null);
      };

这似乎不是最干净的解决方案,有没有更好的方法来解决这个问题?

另外,如果我想在基本 Xamarin.Forms 控件上触发一个事件,例如 Clicked,我将如何处理?我是否会覆盖 ButtonControl 中的 Clicked 事件而不是从 Button 类继承并添加一个方法来从那里触发事件?

【问题讨论】:

    标签: c# mvvm xamarin xamarin.forms


    【解决方案1】:

    button.Tapped += handler 是您的做法。但无需执行命令,您只需在 Element 上调用 SendClicked()。这将执行命令触发Clicked 事件。标准渲染器也在做同样的事情。

    您应该将匿名委托转换为您的类中的方法,以便能够在清理时取消注册事件,以防止内存泄漏。

    public class ButtonControlRenderer : ViewRenderer<ButtonControl, Button>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<ButtonControl> e)
        {
            //your creation code ...            
            button.Tapped += OnButtonTapped;
        }
    
        private void OnButtonTapped(...)
        {
            ((IButtonController)Element)?.SendClicked();
        }
    
        protected override void Dispose(bool disposing)
        {
            if (Control != null)
                Control.Tapped -= OnButtonTapped;
    
            base.Dispose(disposing);
        }
    }
    

    【讨论】:

    • 完美,非常感谢,正在寻找一种方法,但没有强制转换为 IButtonController,因此从未找到它。关于处置的好建议!
    猜你喜欢
    • 1970-01-01
    • 2021-08-25
    • 1970-01-01
    • 2014-08-29
    • 2016-05-31
    • 2017-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多