Reputation: 2241
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
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