MattB
MattB

Reputation: 2241

WPF Grid Faded in on Top of Other Grids Has Inactive Controls

I'm experiencing some unexpected behavior with a UI I'm working on for a C# WPF application.

The cliffnotes version is that I have 3 Grids that all "inhabit" the same area on the form. Based on some toggle buttons those grids are enabled or disabled and faded in and out of view. However, it seems that in some cases certain TextBoxes can be used and others cannot.

Here is the style I'm applying:

    <!-- Fade in/out style for grid -->
    <Style
        x:Key="FadeInOutStyle"
        TargetType="Grid">
        <Style.Triggers>
            <Trigger
                Property="IsEnabled"
                Value="True">
                <Trigger.Setters>
                    <Setter 
                        Property="Panel.ZIndex"
                        Value="1"/>
                </Trigger.Setters>
                <Trigger.EnterActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation
                                Storyboard.TargetProperty="Opacity"
                                From="0.0"
                                To="1.0"
                                Duration="0:0:0.8"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard>
                        <Storyboard>
                            <DoubleAnimation
                                Storyboard.TargetProperty="Opacity"
                                From="1.0"
                                To="0.0"
                                Duration="0:0:0.4"/>
                        </Storyboard>
                    </BeginStoryboard>
                </Trigger.ExitActions>
            </Trigger>
            <Trigger
                Property="IsEnabled"
                Value="False">
                <Trigger.Setters>
                    <Setter
                        Property="Panel.ZIndex"
                        Value="0"/>
                </Trigger.Setters>
            </Trigger>
        </Style.Triggers>

The style seems to apply just fine, the grids fade into and out of view as expected. Here's one of the "checked" functions that enables the checked grid and disables the others. If you want to see the rest just say so, but it would be a bit dog and pony show:

    private void IndividualRadio_Checked(object sender, RoutedEventArgs e)
    {
        this.TwoIndividualGrid.IsEnabled = false;
        this.CommercialGrid.IsEnabled = false;
        this.IndividualGrid.IsEnabled = true;
    }

And here is the XAML for one of the grids. They all have nothing more than labels and TextBox controls. They all start with the same margins and similar dimmensions:

        <Grid
            Name="IndividualGrid"
            IsEnabled="False"
            Height="30"
            Width="420"
            Opacity="0"
            HorizontalAlignment="Left"
            VerticalAlignment="Top"
            Margin="10,90,0,0"
            Style="{StaticResource FadeInOutStyle}"
            Panel.ZIndex="0">
            <Label
                Content="First Name"
                Height="25"
                Width="90"
                VerticalAlignment="Top"
                HorizontalAlignment="Left"
                Margin="0,0,0,0"/>
            <TextBox
                Name="SubjFirstNameBox"
                Height="30"
                Width="100"
                VerticalAlignment="Top"
                HorizontalAlignment="Left"
                Style="{StaticResource ValidationStyle}"
                Margin="100,0,0,0">
                <TextBox.Text>
                    <Binding 
                        Path="SubjFirstName" 
                        Mode="TwoWay">
                        <Binding.ValidationRules>
                            <ExceptionValidationRule/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>
            <Label
                Content="Last Name"
                Height="25"
                Width="90"
                VerticalAlignment="Top"
                HorizontalAlignment="Left"
                Margin="210,0,0,0"/>
            <TextBox
                Name="SubjLastNameBox"
                Height="30"
                Width="100"
                VerticalAlignment="Top"
                HorizontalAlignment="Left"
                Style="{StaticResource ValidationStyle}"
                Margin="310,0,0,0">
                <TextBox.Text>
                    <Binding 
                        Path="SubjLastName" 
                        Mode="TwoWay">
                        <Binding.ValidationRules>
                            <ExceptionValidationRule/>
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>
            </TextBox>
        </Grid>

And, just because I know someone might ask to see it, here are a couple examples of the properties I've binded. In this case, the First Name/SubjFirstName textbox does not work but the Last Name/SubjLastName textbox does:

    private string subjFirstName;
    public string SubjFirstName
    {
        get { return subjFirstName; }
        set { subjFirstName = value; }
    }

    private string subjLastName;
    public string SubjLastName
    {
        get { return subjLastName; }
        set { subjLastName = value; }
    }

So, does anyone see what I'm messing up here? I'm assuming it has to be the stacked grids, so if someone has a better approach I'd love to hear it. I'm fairly certain I've done it this way before though, and I'd think that disabling and setting the panel index would do the trick.

Upvotes: 1

Views: 186

Answers (1)

k1ll3r8e
k1ll3r8e

Reputation: 747

Soo, after an deeper view, i found now the following things which in my mind can cause this bug.

<TextBox Name="SubjLastNameBox" Height="30" Width="100" VerticalAlignment="Top" HorizontalAlignment="Left" Style="{StaticResource ValidationStyle}" Margin="310,0,0,0">
<TextBox.Text>
    <Binding Path="SubjLastName" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
        <Binding.ValidationRules>
            <ExceptionValidationRule/>
        </Binding.ValidationRules>
    </Binding>
</TextBox.Text>

As you can see i added UpdateSourceTrigger="PropertyChanged" this is really important if you use Mode="TwoWay". Also, as described in my comment you need to add INotifyPropertyChanged to your view-model.

//using System.ComponentModel;

public class MyClass : INotifyPropertyChanged
{
    private string _subjLastName;

    ///<summary>
    /// public lastname property
    ///</summary>
    public string SubjLastName
    {
        get
        {
            return _subjLastName;
        }
        set
        {
            // The if statement here is importent! So you only raise the notification if the value has changed
            if (_subjLastName != value)
            {
                _subjLastName = value;
                OnPropertyChanged("SubjLastName");
            }
        }
    }

    #region INotify

    #region OnPropertyChanged + Handler

    ///<summary>
    /// PropertyChanged event handler
    ///</summary>
    public event PropertyChangedEventHandler PropertyChanged;

    ///<summary>
    /// Notify the UI for changes
    ///</summary>
    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    #endregion

    #endregion
}

EDIT:
Another solution might be:

<Trigger Property="IsEnabled" Value="False">
    <Trigger.Setters>
        <Setter Property="Visibility" Value="Collapsed"/>
    </Trigger.Setters>
</Trigger>

<Trigger Property="IsEnabled" Value="true">
    <Trigger.Setters>
        <Setter Property="Visibility" Value="Visible"/>
    </Trigger.Setters>
</Trigger>

Here i use Property="Visibility" instead of Property="Panel.ZIndex" so you hide the complete control if it's not used or you show it if it's used. (You have to tune it a bit because you want to show the fade? If so, you need to bring it back to Visible before you begin to fade it in. Also you have to Collapse it after the fade out.)

Hope this will fix your issue.

Upvotes: 1

Related Questions