diff --git a/Xamarin.Forms.ControlGallery.WPF/MainWindow.xaml.cs b/Xamarin.Forms.ControlGallery.WPF/MainWindow.xaml.cs index 4285e355d..e0b4a5e13 100644 --- a/Xamarin.Forms.ControlGallery.WPF/MainWindow.xaml.cs +++ b/Xamarin.Forms.ControlGallery.WPF/MainWindow.xaml.cs @@ -10,7 +10,7 @@ namespace Xamarin.Forms.ControlGallery.WPF public MainWindow() { InitializeComponent(); - Forms.SetFlags("CarouselView_Experimental", "MediaElement_Experimental"); + Forms.SetFlags("CarouselView_Experimental", "MediaElement_Experimental", "RadioButton_Experimental"); Xamarin.Forms.Forms.Init(); FormsMaps.Init(""); LoadApplication(new Controls.App()); diff --git a/Xamarin.Forms.Platform.WPF/FormsRadioButton.cs b/Xamarin.Forms.Platform.WPF/FormsRadioButton.cs new file mode 100644 index 000000000..10820ad5b --- /dev/null +++ b/Xamarin.Forms.Platform.WPF/FormsRadioButton.cs @@ -0,0 +1,67 @@ +using WContentPresenter = System.Windows.Controls.ContentPresenter; +using System.Windows; +using System.Windows.Media; +using Xamarin.Forms.Platform.WPF.Controls; + +namespace Xamarin.Forms.Platform.WPF +{ + public class FormsRadioButton : System.Windows.Controls.RadioButton + { + public static readonly DependencyProperty BorderRadiusProperty = DependencyProperty.Register(nameof(BorderRadius), typeof(int), typeof(FormsButton), + new PropertyMetadata(default(int), OnBorderRadiusChanged)); + + public static readonly DependencyProperty BackgroundColorProperty = DependencyProperty.Register(nameof(BackgroundColor), typeof(Brush), typeof(FormsButton), + new PropertyMetadata(default(Brush), OnBackgroundColorChanged)); + + + public Brush BackgroundColor + { + get + { + return (Brush)GetValue(BackgroundColorProperty); + } + set + { + SetValue(BackgroundColorProperty, value); + } + } + + public int BorderRadius + { + get + { + return (int)GetValue(BorderRadiusProperty); + } + set + { + SetValue(BorderRadiusProperty, value); + } + } + + public override void OnApplyTemplate() + { + base.OnApplyTemplate(); + + UpdateBackgroundColor(); + } + + static void OnBackgroundColorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((FormsRadioButton)d).UpdateBackgroundColor(); + } + + static void OnBorderRadiusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + + } + + void UpdateBackgroundColor() + { + if (BackgroundColor == null) + BackgroundColor = Background; + + Background = BackgroundColor; + } + + } +} diff --git a/Xamarin.Forms.Platform.WPF/Properties/AssemblyInfo.cs b/Xamarin.Forms.Platform.WPF/Properties/AssemblyInfo.cs index 33ab2f812..74980f40d 100644 --- a/Xamarin.Forms.Platform.WPF/Properties/AssemblyInfo.cs +++ b/Xamarin.Forms.Platform.WPF/Properties/AssemblyInfo.cs @@ -2,13 +2,14 @@ using System.Runtime.InteropServices; using System.Windows; using Xamarin.Forms; -using Xamarin.Forms.Platform.WPF; +using Xamarin.Forms.Platform.WPF; [assembly: ThemeInfo(ResourceDictionaryLocation.None, ResourceDictionaryLocation.SourceAssembly)] [assembly: ExportRenderer(typeof(Layout), typeof(LayoutRenderer))] [assembly: ExportRenderer(typeof(Label), typeof(LabelRenderer))] [assembly: ExportRenderer(typeof(Button), typeof(ButtonRenderer))] +[assembly: ExportRenderer(typeof(RadioButton), typeof(RadioButtonRenderer))] [assembly: ExportRenderer(typeof(BoxView), typeof(BoxViewRenderer))] [assembly: ExportRenderer(typeof(Switch), typeof(SwitchRenderer))] [assembly: ExportRenderer(typeof(DatePicker), typeof(DatePickerRenderer))] diff --git a/Xamarin.Forms.Platform.WPF/Renderers/RadioButtonRenderer.cs b/Xamarin.Forms.Platform.WPF/Renderers/RadioButtonRenderer.cs new file mode 100644 index 000000000..cce078e98 --- /dev/null +++ b/Xamarin.Forms.Platform.WPF/Renderers/RadioButtonRenderer.cs @@ -0,0 +1,204 @@ +using System.ComponentModel; +using System.Windows; +using System.Windows.Media; +using WThickness = System.Windows.Thickness; + +namespace Xamarin.Forms.Platform.WPF +{ + public class RadioButtonRenderer : ViewRenderer + { + bool _fontApplied; + bool _isDisposed; + FormsRadioButton _button; + + protected override void OnElementChanged(ElementChangedEventArgs e) + { + base.OnElementChanged(e); + + if (e.NewElement != null) + { + if (Control == null) + { + _button = new FormsRadioButton(); + + _button.Click += OnButtonClick; + _button.AddHandler(System.Windows.Controls.Button.ClickEvent, (RoutedEventHandler)OnPointerPressed, true); + _button.Checked += OnRadioButtonCheckedOrUnchecked; + _button.Unchecked += OnRadioButtonCheckedOrUnchecked; + + SetNativeControl(_button); + } + + UpdateContent(); + + //TODO: We may want to revisit this strategy later. If a user wants to reset any of these to the default, the UI won't update. + if (Element.IsSet(VisualElement.BackgroundColorProperty) && Element.BackgroundColor != (Color)VisualElement.BackgroundColorProperty.DefaultValue) + UpdateBackground(); + + if (Element.IsSet(RadioButton.TextColorProperty) && Element.TextColor != (Color)RadioButton.TextColorProperty.DefaultValue) + UpdateTextColor(); + + if (Element.IsSet(RadioButton.BorderColorProperty) && Element.BorderColor != (Color)RadioButton.BorderColorProperty.DefaultValue) + UpdateBorderColor(); + + if (Element.IsSet(RadioButton.BorderWidthProperty) && Element.BorderWidth != (double)RadioButton.BorderWidthProperty.DefaultValue) + UpdateBorderWidth(); + + if (Element.IsSet(RadioButton.CornerRadiusProperty) && Element.CornerRadius != (int)RadioButton.CornerRadiusProperty.DefaultValue) + UpdateBorderRadius(); + + if (Element.IsSet(RadioButton.PaddingProperty) && Element.Padding != (Thickness)RadioButton.PaddingProperty.DefaultValue) + UpdatePadding(); + + UpdateFont(); + UpdateCheck(); + } + } + + protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) + { + base.OnElementPropertyChanged(sender, e); + + if (e.PropertyName == RadioButton.TextProperty.PropertyName || e.PropertyName == Button.ImageSourceProperty.PropertyName) + { + UpdateContent(); + } + else if (e.PropertyName == VisualElement.BackgroundColorProperty.PropertyName) + { + UpdateBackground(); + } + else if (e.PropertyName == RadioButton.TextColorProperty.PropertyName) + { + UpdateTextColor(); + } + else if (e.PropertyName == RadioButton.FontProperty.PropertyName) + { + UpdateFont(); + } + else if (e.PropertyName == RadioButton.BorderColorProperty.PropertyName) + { + UpdateBorderColor(); + } + else if (e.PropertyName == RadioButton.BorderWidthProperty.PropertyName) + { + UpdateBorderWidth(); + } + else if (e.PropertyName == RadioButton.CornerRadiusProperty.PropertyName) + { + UpdateBorderRadius(); + } + else if (e.PropertyName == RadioButton.PaddingProperty.PropertyName) + { + UpdatePadding(); + } + else if (e.PropertyName == RadioButton.IsCheckedProperty.PropertyName) + { + UpdateCheck(); + } + } + + + + void OnButtonClick(object sender, RoutedEventArgs e) + { + ((IButtonController)Element)?.SendReleased(); + ((IButtonController)Element)?.SendClicked(); + } + + void OnPointerPressed(object sender, RoutedEventArgs e) + { + ((IButtonController)Element)?.SendPressed(); + } + + void OnRadioButtonCheckedOrUnchecked(object sender, RoutedEventArgs e) + { + if (Element == null || Control == null) + { + return; + } + + Element.IsChecked = Control.IsChecked == true; + } + + protected override void UpdateBackground() + { + Control.BackgroundColor = Element.BackgroundColor != Color.Default ? Element.BackgroundColor.ToBrush() : (Brush)System.Windows.Application.Current.Resources["ButtonBackgroundThemeBrush"]; + } + + void UpdateBorderColor() + { + Control.BorderBrush = Element.BorderColor != Color.Default ? Element.BorderColor.ToBrush() : (Brush)System.Windows.Application.Current.Resources["ButtonBorderThemeBrush"]; + } + + void UpdateBorderRadius() + { + Control.BorderRadius = Element.CornerRadius; + } + + void UpdateBorderWidth() + { + Control.BorderThickness = Element.BorderWidth == (double)RadioButton.BorderWidthProperty.DefaultValue ? new WThickness(3) : new WThickness(Element.BorderWidth); + } + + void UpdateContent() + { + Control.Content = Element.Text; + } + + void UpdateFont() + { + if (Control == null || Element == null) + return; + + if (Element.Font == Font.Default && !_fontApplied) + return; + + Font fontToApply = Element.Font == Font.Default ? Font.SystemFontOfSize(NamedSize.Medium) : Element.Font; + + Control.ApplyFont(fontToApply); + _fontApplied = true; + } + + void UpdateTextColor() + { + Control.Foreground = Element.TextColor != Color.Default ? Element.TextColor.ToBrush() : (Brush)System.Windows.Application.Current.Resources["DefaultTextForegroundThemeBrush"]; + } + + void UpdatePadding() + { + Control.Padding = new WThickness( + Element.Padding.Left, + Element.Padding.Top, + Element.Padding.Right, + Element.Padding.Bottom + ); + } + + void UpdateCheck() + { + if (Control == null || Element == null) + { + return; + } + + Control.IsChecked = Element.IsChecked; + } + + protected override void Dispose(bool disposing) + { + if (_isDisposed) + return; + if (_button != null) + { + _button.Click -= OnButtonClick; + _button.RemoveHandler(System.Windows.Controls.Button.ClickEvent, (RoutedEventHandler)OnPointerPressed); + _button.Checked -= OnRadioButtonCheckedOrUnchecked; + _button.Unchecked -= OnRadioButtonCheckedOrUnchecked; + } + + _isDisposed = true; + + base.Dispose(disposing); + } + } +}