jyavenard
jyavenard

Reputation: 2095

Transparent canvas, with opaque elements

I'm trying to simulate an Android UI element that unfortunately doesn't exist in Windows 7 phone: ListPreference

I thought about using a Popup, that would take exactly the whole screen (to simulate a modal window).

So the popup would be made of the following elements:

Popup -> Canvas -> Border -> StackPanel -> RadioButtons

The Canvas would be fully transparent (or lightly whitish to clearly show that the element underneath aren't available)

The border would be made so it only big enough to contain all the RadioButtons Then the StackPanel would be opaque and black.

Unfortunately, if I make the bottom canvas transparent, all children elements are also transparent. I can only make the elements more transparent.

The way transparency works is slightly different than with Android or iPhone (where it's quite easy to have a parent fully transparent, but opaque children).

Is there a way to make a parent fully transparent with the children opaque?

Or maybe someone could suggest another way to simulate a modal window. Who knows, maybe someone even developed a ListPreference-like UIElement :)

Thank you

Upvotes: 0

Views: 2020

Answers (2)

jyavenard
jyavenard

Reputation: 2095

Here is how I ended up doing it.

It works in a similar fashion as ListPreference on Android. The constructor takes a string, an array of string and an int indicating which is the default value

When the windows is closed, the delegate Dismissed is called..

So you call it like so:

string[] choices = { "Choice 1", "Choice 2", "Choice3" };
ListPreference lp = new ListPreference("name", choices, 1);
lp.dismissed += new ListPreferences.DismissedHandler(lp_Dismissed);

the code:

public class ListPreference
{
    Popup p;
    string Name;
    int oldValue;

    public delegate void DismissedHandler(string name, bool changed, int newvalue);

    public event DismissedHandler Dismissed;

    public bool IsOpen
    {
        get
        {
            return p.IsOpen;
        }

        set
        {
            p.IsOpen = value;
        }
    }

    public ListPreference(string name, Array elements, int default_value)
    {
        p = new Popup();
        Name = name;
        Dismissed = null;
        oldValue = default_value;

        double height = (App.Current.RootVisual as FrameworkElement).ActualHeight;
        double width = (App.Current.RootVisual as FrameworkElement).ActualWidth;

        p.VerticalOffset = SystemTray.IsVisible ? 32.0 : 0.0;
        p.Height = height;
        p.Width = width;
        Canvas canvas = new Canvas();
        SolidColorBrush colorBrush = new SolidColorBrush(Colors.Black);
        colorBrush.Opacity = 0.75;
        //Color.FromArgb(0xff, 0x8a, 0x8a, 0x8a));
        canvas.Background = colorBrush;
        //canvas.Opacity = 0.765;
        canvas.Height = height;
        canvas.Width = width;
        p.Child = canvas;

        Border border = new Border();
        border.Width = width - 50.0 * 2.0;
        border.BorderBrush = new SolidColorBrush(Colors.LightGray);
        border.BorderThickness = new Thickness(5.0);
        border.Background = new SolidColorBrush(Colors.Black);
        canvas.Children.Add(border);

        StackPanel panel2 = new StackPanel();
        panel2.Orientation = System.Windows.Controls.Orientation.Vertical;

        int i = 0;
        foreach (string val in elements)
        {
            RadioButton radio1 = new RadioButton();
            radio1.GroupName = "group1";
            radio1.Content = val;
            if (i == default_value)
                radio1.IsChecked = true;
            int j = i;
            radio1.Click += (sender, args) => radio1_Checked(radio1, j);
            i++;
            panel2.Children.Add(radio1);
        }

        Button button1 = new Button();
        button1.Background = new SolidColorBrush(Colors.Black);
        button1.Foreground = new SolidColorBrush(Colors.White);
        button1.Opacity = 1.0;
        button1.Content = "Cancel";
        button1.Margin = new Thickness(5.0);
        button1.Click += new RoutedEventHandler(closeButton_Click);
        panel2.Children.Add(button1);
        border.Child = panel2;

        // Open the popup.
        p.IsOpen = true;
        p.UpdateLayout();
        border.Height = panel2.DesiredSize.Height + 5.0 * 2.0;
        border.SetValue(Canvas.TopProperty, (height - border.Height) / 2.0);
        border.SetValue(Canvas.LeftProperty, (width - border.Width) / 2.0);
        p.UpdateLayout();
    }

    void closeButton_Click(object sender, RoutedEventArgs e)
    {
        // Close the popup.
        p.IsOpen = false;
        if (Dismissed != null)
        {
            Dismissed(Name, false, -1);
        }
    }

    void radio1_Checked(object sender, int idx)
    {
        p.IsOpen = false;
        if (Dismissed != null)
        {
            Dismissed(Name, idx != oldValue, idx);
        }
    }
}

Upvotes: 1

abhinav
abhinav

Reputation: 3217

I would suggest creating a Usercontrol that would do what you need. Set the LayoutRoot grid's background to PhoneSemitransparentBrush or changing the opacity will change the child element's opacity as well. Then your child elements can have any opacity you'd like. You can add this control as a child to the popup. Additionally, you can add doubleanimation to the popup with the opened and closed event triggers. Change the design height of the UserControl to 480x760 to simulate full page.

To answer your question. Using resources like PhoneSemitransparentBrush and TransparentBrush for the Canvas background is one of your options. Opacity will change the opacity of the whole UIElement including its children.

Upvotes: 1

Related Questions