Avrohom Yisroel
Avrohom Yisroel

Reputation: 9440

Custom control not displaying correctly

I'm trying to develop a WPF custom control that can be used to overlay other controls, effectively dimming them out so as to make it clear that they are not usable. This is similar to the effect you see on many web sites, where they grey out the background page when a pop-up is shown.

Trouble is, when it runs, instead of showing the contained controls dimly, they just disappear. I'll show the code below, along with a very simple sample usage.

Here is the code for control itself (namespace and usings omitted to save a bit of space)...

public class OverlayDisableControl : UserControl {
  protected override void OnInitialized(EventArgs e) {
    base.OnInitialized(e);

    VerticalAlignment = VerticalAlignment.Stretch;
    HorizontalAlignment = HorizontalAlignment.Stretch;

    Grid grid = new Grid();

    ContentPresenter content = new ContentPresenter {
      Name = "content",
      Content = Content
    };
    grid.Children.Add(content);

    Grid overlay = new Grid {
      Name = "Overlay",
      Visibility = Visibility.Collapsed
    };

    Border background = new Border {
      Name = "background",
      VerticalAlignment = VerticalAlignment.Stretch,
      HorizontalAlignment = HorizontalAlignment.Stretch,
      Background = new SolidColorBrush(Colors.LightGray),
      Opacity = .6
    };
    overlay.Children.Add(background);

    grid.Children.Add(overlay);

    Content = grid;
  }

  public static readonly DependencyProperty OverlayVisibleProperty =
             DependencyProperty.Register("OverlayVisible", typeof(bool),
             typeof(OverlayDisableControl), 
             new FrameworkPropertyMetadata(SetOverlayVisibleStatic));

  public bool OverlayVisible {
    get {
      return (bool) GetValue(OverlayVisibleProperty);
    }
    set {
      SetValue(OverlayVisibleProperty, value);
    }
  }

  private static void SetOverlayVisibleStatic(DependencyObject d, DependencyPropertyChangedEventArgs e) {
    (d as OverlayDisableControl).SetOverlayVisible(d as OverlayDisableControl, (bool) e.NewValue);
  }

  private void SetOverlayVisible(OverlayDisableControl odc, bool visible) {
    if (visible) {
      DoubleAnimation anim = new DoubleAnimation {
        From = 0,
        To = 1, // Visible
        Duration = new Duration(TimeSpan.FromMilliseconds(350)),
        EasingFunction = new QuadraticEase {
          EasingMode = EasingMode.EaseInOut
        }
      };
      odc.Visibility = Visibility.Visible;
      odc.BeginAnimation(OpacityProperty, anim);
    } else {
      DoubleAnimation anim = new DoubleAnimation {
        From = 1,
        To = 0, // Invisible
        Duration = new Duration(TimeSpan.FromMilliseconds(350)),
        EasingFunction = new QuadraticEase {
          EasingMode = EasingMode.EaseInOut
        }
      };
      anim.Completed += (s1, e1) => {
        odc.Visibility = Visibility.Collapsed;
      };
      odc.BeginAnimation(OpacityProperty, anim);
    }
  }
}

...and here is a sample usage. This is all you need, no code-behind, just drop this onto a window. The controls inside the GroupBox are just there for tesing...

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <StackPanel Orientation="Horizontal">
    <CheckBox Content="Show?"
              Margin="3"
              Name="ShowChk"
              IsChecked="True" />
  </StackPanel>
  <local:OverlayDisableControl OverlayVisible="{Binding ElementName=ShowChk, Path=IsChecked, Mode=TwoWay}"
                               Grid.Row="1">
    <GroupBox Header="Gratuitous controls"
              Margin="3">
      <StackPanel Orientation="Vertical">
        <TextBlock Text="This is some text"
                   Margin="3" />
        <TextBox Margin="3" />
        <Button Content="Save"
                Margin="3" />
      </StackPanel>
    </GroupBox>
  </local:OverlayDisableControl>
</Grid>

Anyone any idea what I've done wrong?

Upvotes: 0

Views: 67

Answers (1)

Funk
Funk

Reputation: 11201

You're animating / changing visibility of the UserControl itself, while it's the Grid overlay you're after.

Changes to your code:

public class OverlayDisableControl : UserControl
{
    private Grid overlay = new Grid
    {
        Name = "Overlay",
        Visibility = Visibility.Collapsed
    };

    protected override void OnInitialized(EventArgs e)
    {
        base.OnInitialized(e);

        ...

        //Grid overlay = new Grid
        //{
        //    Name = "Overlay",
        //    Visibility = Visibility.Collapsed
        //};

        ...

    }

    ...

    private static void SetOverlayVisibleStatic(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        (d as OverlayDisableControl).SetOverlayVisible((bool)e.NewValue);
    }

    private void SetOverlayVisible(bool visible)
    {
        if (visible)
        {
            DoubleAnimation anim = new DoubleAnimation
            {
                ...
            };
            overlay.Visibility = Visibility.Visible;
            overlay.BeginAnimation(OpacityProperty, anim);
        }
        else
        {
            DoubleAnimation anim = new DoubleAnimation
            {
                ...
            };
            anim.Completed += (s1, e1) => {
                overlay.Visibility = Visibility.Collapsed;
            };
            overlay.BeginAnimation(OpacityProperty, anim);
        }
    }
}

Upvotes: 1

Related Questions