Geo242
Geo242

Reputation: 597

WPF visibility binding not playing well with data trigger bound to visibility

I can't figure out what the problem with this code is. Maybe you can spot something I don't see. My project builds just fine and the designer doesn't complain about anything. But, when I try to run it, it says that it can't create an instance of the window this code is in.

I think I have narrowed the problem down to the visibility binding coordinating with the data trigger. If I remove the visibility binding on that property and set it arbitrarily to true or false, it runs just fine. But I need this property to be dynamic.

<Image Visibility="{Binding ShowStatusMessageTabIcon, Converter={StaticResource BoolToVisibility}}"
   Source="{Binding Source={x:Static bo:UserSession.Instance}, Path=HighestStatusMessageSeverity, Converter={StaticResource SeverityToImageConverter}}">
<Image.Style>
    <Style>
        <Style.Triggers>
            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Visibility}"
                         Value="Visible">
                <DataTrigger.EnterActions>
                    <BeginStoryboard Storyboard="{StaticResource FlashErrorImage}" />
                </DataTrigger.EnterActions>
                <DataTrigger.ExitActions>
                    <RemoveStoryboard BeginStoryboardName="FlashErrorImage" />
                </DataTrigger.ExitActions>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Image.Style>

Upvotes: 0

Views: 3861

Answers (1)

sa_ddam213
sa_ddam213

Reputation: 43606

If your using a Trigger on a property of the UIElement itself you will want to use Trigger not DataTrigger, DataTriggers are more for changes in DataObjects in your model etc, normal Triggers are used for the UIElements etc.

   <Image.Style>
        <Style TargetType="{x:Type Image}">
            <Style.Triggers>
                <Trigger Property="Visibility" Value="Visible">
                    <Trigger.EnterActions>
                        <BeginStoryboard Storyboard="{StaticResource FlashErrorImage}" />
                    </Trigger.EnterActions>
                    <Trigger.ExitActions>
                        <RemoveStoryboard BeginStoryboardName="FlashErrorImage" />
                    </Trigger.ExitActions>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Image.Style>

Here is a complete working mockup, if it helps narrow down the issue

Xaml:

<Window x:Class="WpfApplication7.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Name="UI">

    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />

        <Storyboard x:Key="FadeAnimation" Storyboard.TargetProperty="Opacity" >
            <DoubleAnimation From="0" To="1" Duration="0:0:5" />
        </Storyboard>
    </Window.Resources>

    <StackPanel>
        <Image Source="http://icons.iconarchive.com/icons/iconcreme/halloween/128/Skeleton-icon.png" 
               Visibility="{Binding ElementName=UI, Path=ImageVisible, Converter={StaticResource BooleanToVisibilityConverter}}" Height="247">
        <Image.Style>
            <Style TargetType="{x:Type Image}">
                <Style.Triggers>
                    <Trigger Property="Visibility" Value="Visible">
                        <Trigger.EnterActions>
                                <BeginStoryboard Name="Fade" Storyboard="{StaticResource FadeAnimation}" />
                        </Trigger.EnterActions>
                        <Trigger.ExitActions>
                             <RemoveStoryboard BeginStoryboardName="Fade"  />
                        </Trigger.ExitActions>
                    </Trigger>
                </Style.Triggers>
            </Style>
        </Image.Style>
    </Image>
        <Button Click="Button_Click" Content="Visible"/>
    </StackPanel>
</Window>

Code:

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private bool _imageVisible;
    public MainWindow()
    {
        InitializeComponent();
    }

    public bool ImageVisible
    {
        get { return _imageVisible; }
        set { _imageVisible = value; NotifyPropertyChanged("ImageVisible"); }
    }

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        ImageVisible = !ImageVisible;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string p)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(p));
        }
    }
}

Upvotes: 1

Related Questions