0

I have a Style for my Button I want to change my window's WindowState property to maximized when my Button Click Event Fired from style without any code behind . I have tried this but is not working. And this error Came up : "Cannot resolve all property references in the property path 'WindowState'. Verify that applicable objects support the properties."

Do you have any working idea please.

<Window x:Class="MyTestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyTestApp"
        mc:Ignorable="d"
        x:Name="ss"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="Button">
            <Style.Triggers>               
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard >
                            <ObjectAnimationUsingKeyFrames 
                                Storyboard.Target="{Binding RelativeSource={RelativeSource AncestorType=Window ,Mode=FindAncestor }}" 
                                Storyboard.TargetProperty="WindowState"
                                >
                                <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                    <DiscreteObjectKeyFrame.Value>
                                        <WindowState>Maximized</WindowState>
                                    </DiscreteObjectKeyFrame.Value>
                                </DiscreteObjectKeyFrame>

                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>

                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <StackPanel Width="200" Height="200" Background="Aqua">
        <Button Content="Click me !" Width="100" Height="50"/>
        </StackPanel>
    </Grid>
</Window> 

UPDATE 1 :

I have a new Problem.I created two buttons , one for maximize State one for Normal State.if i use just this two buttons there is no problem. I Tried to Maximize my window by window's Maximize Button, then my Styled Normal Button didn't work !! if I maximize window by clicking window's maximize button then my styled normal button didn't work.So if i click my styled maximize button my styled normal button work again. whats wrong ?

<Window x:Class="MyTestApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MyTestApp"
        StateChanged="ss_StateChanged"
        mc:Ignorable="d"
        x:Name="ss"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <Style TargetType="Button" x:Key="MaximizedButtonStyle">
            <Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>
            <Style.Triggers>              

                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard >
                            <ObjectAnimationUsingKeyFrames  Storyboard.TargetProperty="Tag.WindowState"                        >
                                <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                    <DiscreteObjectKeyFrame.Value>
                                        <WindowState>Maximized</WindowState>
                                    </DiscreteObjectKeyFrame.Value>
                                </DiscreteObjectKeyFrame>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>

                </EventTrigger>
            </Style.Triggers>
        </Style>

        <Style TargetType="Button" x:Key="NormalButtonStyle">
            <Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource AncestorType=Window}}"/>
            <Style.Triggers>              
                <EventTrigger RoutedEvent="Button.Click">
                    <BeginStoryboard>
                        <Storyboard >
                            <ObjectAnimationUsingKeyFrames  Storyboard.TargetProperty="Tag.WindowState"                        >
                                <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                    <DiscreteObjectKeyFrame.Value>
                                        <WindowState>Normal</WindowState>
                                    </DiscreteObjectKeyFrame.Value>
                                </DiscreteObjectKeyFrame>
                            </ObjectAnimationUsingKeyFrames>
                        </Storyboard>
                    </BeginStoryboard>

                </EventTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <StackPanel Width="200" Height="200" Background="Aqua">
            <Button x:Name="b1" Style="{StaticResource NormalButtonStyle}" Content="Normal Click me !" Width="100" Height="50" />
            <Button x:Name="b2" Style="{StaticResource MaximizedButtonStyle}" Content="maximize eClick me !" Width="100" Height="50" />            
        </StackPanel>
    </Grid>
</Window> 
Mamad
  • 446
  • 5
  • 22

1 Answers1

1

If you look in the Output pane in Visual Studio, you'll see that RelativeSource is failing. I think it may be failing because the Storyboard is out of the visual tree. The binding ends up looking for WindowState on the Button itself.

Here's a slightly ugly solution that's working for me: Inside the Storyboard, all the binding can "see" is the Button, not the rest of the visual tree. So we'll smuggle the Window into a property of the Button. A more respectable way to do this would be with a BindingProxy. Binding proxies are a useful technique, and worth getting acquainted with.

<Style TargetType="Button" x:Key="MinimizeButtonStyle">
    <Setter 
        Property="Tag" 
        Value="{Binding RelativeSource={RelativeSource AncestorType=Window}}" 
        />
    <Style.Triggers>
        <EventTrigger RoutedEvent="Button.Click">
            <BeginStoryboard>
                <Storyboard >
                    <ObjectAnimationUsingKeyFrames 
                        Storyboard.TargetProperty="Tag.WindowState"
                        >

    <!-- the rest is the same as what you've got -->

Here are the errors I'm seeing in Output with your original code:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:(no path); DataItem=null; target element is 'ObjectAnimationUsingKeyFrames' (HashCode=51442863); target property is 'Target' (type 'DependencyObject')

System.Windows.Data Error: 40 : BindingExpression path error: 'WindowState' property not found on 'object' ''Button' (Name='')'. null

Exception thrown: 'System.InvalidOperationException' in PresentationFramework.dll

An unhandled exception of type 'System.InvalidOperationException' occurred in PresentationFramework.dll

Cannot resolve all property references in the property path 'WindowState'. Verify that applicable objects support the properties.

Community
  • 1
  • 1
  • Thank You it works perfectly but how? can you explain how tag can hold window in itself? – Mamad Jul 23 '19 at 16:53
  • 1
    @Mamad `Tag` is of type `object`, so it can hold a reference to anything. The binding assigns a reference to the Window to `Tag`. Your original binding on `Storyboard.Target` was trying to assign a reference to the Window to `Storyboard.Target` -- same principle, it's just that you had the misfortune to try doing it in a place where the necessary context for the RelativeSource binding wasn't available. – 15ee8f99-57ff-4f92-890c-b56153 Jul 23 '19 at 16:53
  • I have a new Problem.I created two buttons , one for maximize State one for Normal State.if i use just this two buttons there is no problem. I Tried to Maximize my window by window's Maximize Button, then my Styled Normal Button didn't work !! if I maximize window by clicking window's maximize button then my styled normal button didn't work.So if i click my styled maximize button my styled normal button work again. whats wrong ? – Mamad Jul 23 '19 at 18:21
  • @Mamad How could I possibly know what's wrong with your new code, when I haven't seen it yet? – 15ee8f99-57ff-4f92-890c-b56153 Jul 23 '19 at 18:22
  • @Mamad Looks to me like it might be a [dependency property value precedence](https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/dependency-property-value-precedence) issue: Once you set the property value by the titlebar button, that's going to have greater precedence than an animation setter and the setter's value will be disregarded. That being the case, forget the whole style/storyboard/animation thing and just assign a new value to the WindowState in those click handlers. Kind of a bummer, but it'll work. – 15ee8f99-57ff-4f92-890c-b56153 Jul 23 '19 at 19:11