【问题标题】:How to change ancestor's property from a style如何从样式更改祖先的属性
【发布时间】:2019-07-23 15:36:24
【问题描述】:

我的 Button 有一个 Style 我想在我的 Button Click Event Fired from style 没有任何代码的情况下将我的窗口的 WindowState 属性更改为最大化。 我已经尝试过了,但没有工作。 这个错误出现了: “无法解析属性路径 'WindowState' 中的所有属性引用。验证适用的对象是否支持这些属性。”

请问您有什么工作想法吗?

<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> 

更新 1:

我有一个新问题。我创建了两个按钮,一个用于最大化状态,一个用于正常状态。如果我只使用这两个按钮没有问题。我试图通过窗口的最大化按钮最大化我的窗口,然后我的样式正常按钮不起作用!如果我通过单击窗口的最大化按钮来最大化窗口,那么我的样式正常按钮不起作用。所以如果我单击我的样式最大化按钮,我的样式正常按钮将再次工作。怎么了?

<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> 

【问题讨论】:

    标签: wpf


    【解决方案1】:

    如果您查看 Visual Studio 的“输出”窗格,您会发现 RelativeSource 失败。我认为它可能会失败,因为故事板不在视觉树中。绑定最终会在 Button 本身上查找 WindowState。

    这是一个对我有用的稍微难看的解决方案:在情节提要中,所有绑定可以“看到”的是按钮,而不是视觉树的其余部分。因此,我们将把 Window 偷运到 Button 的一个属性中。一个更体面的方法是使用BindingProxy。绑定代理是一种有用的技术,值得熟悉。

    <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 -->
    

    以下是我在原始代码输出中看到的错误:

    System.Windows.Data 错误:4:找不到与引用“RelativeSource FindAncestor,AncestorType='System.Windows.Window',AncestorLevel='1''的绑定源。 BindingExpression:(无路径);数据项=空;目标元素是“ObjectAnimationUsingKeyFrames”(HashCode=51442863);目标属性是“目标”(类型“依赖对象”)

    System.Windows.Data 错误:40:BindingExpression 路径错误:在“对象”“按钮”(名称=“”)上找不到“WindowState”属性。空

    抛出异常:PresentationFramework.dll 中的“System.InvalidOperationException”

    PresentationFramework.dll 中出现“System.InvalidOperationException”类型的未处理异常

    无法解析属性路径“WindowState”中的所有属性引用。验证适用的对象是否支持这些属性。

    【讨论】:

    • 谢谢它完美的工作,但如何?你能解释一下标签是如何保持窗口本身的吗?
    • @Mamad Tag 是object 类型,所以它可以包含对任何东西的引用。该绑定将 Window 的引用分配给 Tag。您在 Storyboard.Target 上的原始绑定试图将 Window 的引用分配给 Storyboard.Target - 原理相同,只是您不幸尝试在没有 RelativeSource 绑定的必要上下文的地方执行此操作可用。
    • 我有一个新问题。我创建了两个按钮,一个用于最大化状态,一个用于正常状态。如果我只使用这两个按钮没有问题。我试图通过窗口的最大化按钮最大化我的窗口,然后我的样式正常按钮不起作用!如果我通过单击窗口的最大化按钮来最大化窗口,那么我的样式正常按钮不起作用。所以如果我单击我的样式最大化按钮,我的样式正常按钮将再次工作。怎么了?
    • @Mamad 我还没有看到你的新代码,我怎么可能知道它有什么问题?
    • @Mamad 在我看来这可能是一个dependency property value precedence 问题:一旦您通过标题栏按钮设置属性值,它将比动画设置器具有更高的优先级,设置器的值将是无视。在这种情况下,忘记整个样式/故事板/动画,只需在这些点击处理程序中为 WindowState 分配一个新值。有点无赖,但它会起作用。
    猜你喜欢
    • 2010-10-13
    • 2021-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-25
    • 2016-09-19
    相关资源
    最近更新 更多