Вопрос

Я создал вложенное свойство зависимостей для раскадровок, чтобы разрешить мне вызывать метод в моей ViewModel при возникновении события «завершение раскадровки»:

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);
    }
}

затем я пытаюсь использовать его в XAML с синтаксисом Binding:

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

Это происходит со следующим исключением:

  

System.Windows.Markup.XamlParseException   Сообщение = " Невозможно преобразовать значение в атрибуте 'Style' в объект типа 'System.Windows.Style'. Невозможно заморозить это дерево шкалы времени раскадровки для использования в разных потоках. Ошибка в объекте labelHello в файле разметки TestWpfApp, component / window1.xaml

Есть ли способ заставить синтаксис Binding работать со вложенным свойством ICommand для раскадровки?

Это было полезно?

Решение 3

Чтобы обойти эту проблему, я создал группу прикрепленных свойств, называемых «Помощники раскадровки» ( исходный код здесь ). Я прекратил попытки прикрепить их к самой раскадровке и теперь присоединяю к любому (произвольному) элементу структуры для вызова ICommand в моей ViewModel после завершения раскадровки, а также привязки к определенному событию в моей ViewModel для запуска раскадровки , Третье прикрепленное свойство определяет раскадровку, с которой мы имеем дело:

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

Другие советы

Это что-то задуманное. Если у вас есть замораживаемый объект, который помещается в стиль, стиль будет заморожен, чтобы обеспечить доступ между потоками. Но привязка - это, по сути, выражение, которое означает, что оно не может быть заморожено, поскольку привязка данных является однопоточной.

Если вам нужно сделать это, поместите триггер вне стиля под элементом рамки, а не в стиле. Вы можете сделать это в разделе Grid.Triggers. Это немного отстой, так как ваш стиль больше не завершен, и вы должны продублировать триггеры, но это «по замыслу» особенность в WPF.

Полный ответ на социальных форумах MSDN: здесь .

Вы можете создать новый класс, производный от Freezable, чтобы запустить раскадровку в виде шимма. Свяжите свойство этого объекта с именем раскадровки. Таким образом, вам не придется дублировать триггеры или хранить их вне стиля.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top