Forum Xamarin.Forms

Announcement:

The Xamarin Forums have officially moved to the new Microsoft Q&A experience. Microsoft Q&A is the home for technical questions and answers at across all products at Microsoft now including Xamarin!

To create new threads and ask questions head over to Microsoft Q&A for .NET and get involved today.

Configuring a native UWP Button

btschumybtschumy Member ✭✭
edited October 2020 in Xamarin.Forms

I have some buttons in a Xamarin Forms app that need some special configuration on UWP. I don't think I can do this in Xaml because the colors I need change depending on the state of the app. I would like to configure this entirely from C#.

I have created an OTButton class that derives from a Xamarin Button. I've created a custom renderer for UWP. Here is the OnElementChanged method where I do the customization:

    using Style = Windows.UI.Xaml.Style;
    using Color = Xamarin.Forms.Color;
    using Setter = Windows.UI.Xaml.Setter;
    using Button = Windows.UI.Xaml.Controls.Button;

    protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Button> e)
    {
        base.OnElementChanged(e);
        if (Control == null)
            return;

        var uwpButton = Control;

        Style style = new Style(typeof(Button));
        style.Setters.Add(new Setter(Button.ForegroundProperty, Utility.TintColor.ToBrush()));
        style.Setters.Add(new Setter(Button.BackgroundProperty, Color.Transparent.ToBrush()));

        uwpButton.Style = style;
    }

This is working, but I need to set the hover and pressed colors as well. I don't seem to find DependencyProperties to do this. It seem like this should be possible. For example, if I put the following in my UWP App.xaml file, the hover color is changed to yellow.

<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.ThemeDictionaries>
            <ResourceDictionary x:Key="Dark">
                <SolidColorBrush x:Key="SystemControlHighlightBaseHighBrush" Color="Yellow" />
            </ResourceDictionary>
        </ResourceDictionary.ThemeDictionaries>
    </ResourceDictionary>
</Application.Resources>

But I can't figure out how to set the "SystemControlHighlightBaseHighBrush" color programmatically. Can anyone help?

Best Answer

  • btschumybtschumy Member ✭✭
    Accepted Answer

    I finally figured out how to do this and am showing the code here for others that have this problem. It is actually very easy. It the Button's custom renderer you can add something like this:

            var uwpButton = Control;
    
            uwpButton.Resources["ButtonForeground"] = Utility.TintColor.MultiplyAlpha(0.95f).ToBrush();
            uwpButton.Resources["ButtonBackground"] = Color.Transparent.ToBrush();
    
            uwpButton.Resources["ButtonForegroundPointerOver"] = Utility.TintColor.MultiplyAlpha(1.0f).ToBrush();
            uwpButton.Resources["ButtonBackgroundPointerOver"] = Utility.TintColor.MultiplyAlpha(0.1f).ToBrush();
    
            uwpButton.Resources["ButtonForegroundPressed"] = Utility.TintColor.MultiplyAlpha(0.75f).ToBrush();
            uwpButton.Resources["ButtonBackgroundPressed"] = Color.Transparent.ToBrush();
    

    So you just modify the UWP button's ResourceDictionary directly and everything is copacetic.

Answers

  • JohnHardmanJohnHardman GBUniversity admin
    edited October 2020

    @btschumy said:
    But I can't figure out how to set the "SystemControlHighlightBaseHighBrush" color programmatically. Can anyone help?

    I had this in some code that I no longer use:

                // This is used as the background color of Buttons when the mouse hovers over them
                Current.Resources["SystemControlBackgroundBaseLowBrush"] =
                    new Windows.UI.Xaml.Media.SolidColorBrush(
                        Windows.UI.Color.FromArgb(
                            0,
                            224,
                            224,
                            224));
    
                // On UWP, this is the text color used when the mouse hovers over a button
                Current.Resources["SystemControlHighlightBaseHighBrush"] =
                    Windows.UI.Color.FromArgb(
                        255,
                        (byte) PaleBlueThemeColorComponentR,
                        (byte) PaleBlueThemeColorComponentG,
                        (byte) PaleBlueThemeColorComponentB);
    

    where Current is Windows.UI.Xaml.Application.Current

    I used to do that on startup of my app, but I would assume that you could do it at any point if you need to change colors dynamically. It's worth a try. I've only just noticed that one of those explicitly uses SolidColorBrush, whilst the other doesn't. You might want to check that.

  • btschumybtschumy Member ✭✭

    Thanks for the suggestion. I've tried it and it doesn't seem to work for me. No errors, but it just doesn't change the colors.

    I've tried setting it on Current and I've also tried setting the value on the button's resources.

  • ColeXColeX Member, Xamarin Team Xamurai

    Does the solution work or not : https://stackoverflow.com/a/39898441/8187800 ?

  • btschumybtschumy Member ✭✭

    @ColeX said:
    Does the solution work or not : https://stackoverflow.com/a/39898441/8187800 ?

    It seems like this is still defining everything in Xaml. I just cannot fathom why this isn't simpler. Why can I not just do something like the following in the custom button renderer:

    uwpButton.ButtonBackgroundPressed = SomeXamarinColor.ToBrush();

    the UWP button only seems to have properties for a small set of resource keys you can set in Xaml.

    To be clear on my needs, I need to configure the buttons to display differently depending on the state of the app. I have a regular mode and a "night vision" mode and the buttons need to behave differently in the two cases.

  • JohnHardmanJohnHardman GBUniversity admin
    edited November 2020

    @btschumy

    @JohnHardman said:
    I had this in some code that I no longer use:

                // This is used as the background color of Buttons when the mouse hovers over them
                Current.Resources["SystemControlBackgroundBaseLowBrush"] =
                    new Windows.UI.Xaml.Media.SolidColorBrush(
                        Windows.UI.Color.FromArgb(
                            0,
                            224,
                            224,
                            224));
    
                // On UWP, this is the text color used when the mouse hovers over a button
                Current.Resources["SystemControlHighlightBaseHighBrush"] =
                    Windows.UI.Color.FromArgb(
                        255,
                        (byte) PaleBlueThemeColorComponentR,
                        (byte) PaleBlueThemeColorComponentG,
                        (byte) PaleBlueThemeColorComponentB);
    

    where Current is Windows.UI.Xaml.Application.Current

    Out of curiosity, I just popped that code back into my codebase. The first bit didn't make any visible difference, the second did. I haven't had time to investigate further, as to whether the first bit not making a difference any more is due to something I changed in my codebase, a change in XF, or a change in Windows/UWP. Let's just say that when I last used that code, I was using a much older version of XF (I am now using XF 4.8).

  • btschumybtschumy Member ✭✭
    Accepted Answer

    I finally figured out how to do this and am showing the code here for others that have this problem. It is actually very easy. It the Button's custom renderer you can add something like this:

            var uwpButton = Control;
    
            uwpButton.Resources["ButtonForeground"] = Utility.TintColor.MultiplyAlpha(0.95f).ToBrush();
            uwpButton.Resources["ButtonBackground"] = Color.Transparent.ToBrush();
    
            uwpButton.Resources["ButtonForegroundPointerOver"] = Utility.TintColor.MultiplyAlpha(1.0f).ToBrush();
            uwpButton.Resources["ButtonBackgroundPointerOver"] = Utility.TintColor.MultiplyAlpha(0.1f).ToBrush();
    
            uwpButton.Resources["ButtonForegroundPressed"] = Utility.TintColor.MultiplyAlpha(0.75f).ToBrush();
            uwpButton.Resources["ButtonBackgroundPressed"] = Color.Transparent.ToBrush();
    

    So you just modify the UWP button's ResourceDictionary directly and everything is copacetic.

Sign In or Register to comment.