Pergunta

Eu criei uma propriedade de dependência anexado para storyboards, com a intenção de me permitindo chamar um método no meu ViewModel quando um Storyboard Concluído evento dispara:

public static class StoryboardExtensions
{
    public static ICommand GetCompletedCommand(DependencyObject target)
    {
        return (ICommand)target.GetValue(CompletedCommandProperty);
    }

    public static void SetCompletedCommand(DependencyObject target, ICommand value)
    {
        target.SetValue(CompletedCommandProperty, value);
    }

    public static readonly DependencyProperty CompletedCommandProperty =
        DependencyProperty.RegisterAttached(
            "CompletedCommand",
            typeof(ICommand),
            typeof(StoryboardExtensions),
            new FrameworkPropertyMetadata(null, OnCompletedCommandChanged));

    static void OnCompletedCommandChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
    {
        Storyboard storyboard = target as Storyboard;
        if (storyboard == null) throw new InvalidOperationException("This behavior can be attached to Storyboard item only.");
        storyboard.Completed += new EventHandler(OnStoryboardCompleted);
    }

    static void OnStoryboardCompleted(object sender, EventArgs e)
    {                        
        Storyboard item = ... // snip
        ICommand command = GetCompletedCommand(item);
        command.Execute(null);
    }
}

então eu tento usá-lo em XAML, com uma sintaxe de Ligação:

<Grid>
    <Grid.Resources>
        <Storyboard x:Key="myStoryboard" my:StoryboardExtensions.CompletedCommand="{Binding AnimationCompleted}">
            <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1" To="0" Duration="0:0:5" />
        </Storyboard>

        <Style x:Key="myStyle" TargetType="{x:Type Label}">
            <Style.Triggers>
                <DataTrigger 
                 Binding="{Binding Path=QuestionState}" Value="Correct">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard Storyboard="{StaticResource myStoryboard}" />
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>

    </Grid.Resources>
    <Label x:Name="labelHello" Grid.Row="0" Style="{StaticResource myStyle}">Hello</Label>
</Grid>

Esta falha com a seguinte exceção:

System.Windows.Markup.XamlParseException ocorreu . Message = "Não é possível converter o valor no atributo 'Estilo' para objeto do tipo 'System.Windows.Style' Não é possível congelar esta árvore cronograma Storyboard para uso em tópicos Erro no objeto 'labelHello' no arquivo de marcação 'TestWpfApp;. / Window1 componente .xaml'

Existe alguma maneira de obter a sintaxe de ligação trabalhar com um ICommand propriedade anexada por um Storyboard?

Foi útil?

Solução 3

Para contornar este problema, eu criei um monte de propriedades anexadas, chamado Storyboard Ajudantes ( código aqui fonte). Eu desisti de tentar anexá-los ao próprio Storyboard, e agora anexar a qualquer (arbitrária) elemento de estrutura para chamar um ICommand no meu ViewModel quando o storyboard é concluída, bem como a ligação a um evento específico no meu ViewModel para lançar o Storyboard . Uma terceira propriedade anexada especifica o Storyboard estamos lidando com:

<FrameworkElement
   my:StoryboardHelpers.Storyboard="{StaticResource rightAnswerAnimation}"
   my:StoryboardHelpers.Completed="{Binding CompletedCommand}"
   my:StoryboardHelpers.BeginEvent="{Binding StartCorrectAnswer}" />

Outras dicas

Isso é algo pelo design. Se você tem um objeto freezable que é colocado em um estilo, o estilo será congelada para permitir o acesso cross-fio. Mas a ligação é essencialmente uma expressão que significa que não podem ser congelados como a ligação de dados é único segmento.

Se você precisar fazer isso, coloque o gatilho fora do estilo sob um elemento de estrutura, em vez de em um estilo. Você pode fazer isso na sua seção Grid.Triggers. Isso faz chupar um pouco como o seu estilo não é mais completo e você tem que duplicar os gatilhos, mas é um recurso de "by design" no WPF.

A resposta completa em fóruns sociais MSDN é aqui .

Você pode criar uma nova classe Freezable derivado para lançar um storyboard como um calço. Bind uma propriedade no objeto calço para o nome do storyboard. Dessa forma, você não terá que duplicar gatilhos ou armazená-los fora do estilo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top