Изменение состояния SIlverlight VSM на целевые элементы в ItemsControl - PullRequest
0 голосов
/ 29 марта 2009

У меня есть ItemsControl с элементами, добавляемыми через привязку данных к наблюдаемой коллекции. Каждый элемент имеет шаблон данных, который определяет его внешний вид.

Я пытаюсь выяснить, возможно ли применять / запускать анимацию к / на каждом из элементов в ItemsControl, когда VisualStateManager переводит ItemsControl в определенное состояние.

Ниже приведена картинка - когда элемент управления переходит в закрытое состояние - я хочу, чтобы элементы в элементе управления сжимались, а также скрывали текст и отображали число. Возможно ли это с помощью VSM или мне нужно прикреплять анимации к каждому элементу при их создании, а затем вручную отключать их, когда я хочу, чтобы они изменили визуальное состояние.

альтернативный текст http://www.edefine.com/images/misc/drawing1.jpg

Ответы [ 2 ]

3 голосов
/ 02 апреля 2009

Это возможно при использовании ObjectAnimationUsingKeyFrames, однако это глупо сложно сделать, заставит вас рвать волосы, регулярно ломать вашу визуальную студию и дает вам совсем немного над этим простым способом.

Простой способ:

public class TestSwapContentControl : ContentControl 
{
    object StoredOriginalContent;

    public object FullContent
    {
        get { return (object)GetValue(FullContentProperty); }
        set { SetValue(FullContentProperty, value); }
    }

    // Using a DependencyProperty as the backing store for FullContent.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FullContentProperty =
        DependencyProperty.Register(
            "FullContent"
            , typeof(object)
            , typeof(TestSwapContentControl)
            , null);

    public void SwitchToFullContent()
    {
        if (FullContent != null)
        {
            StoredOriginalContent = Content;
            Content = FullContent;
        }
    }

    public void SwitchToNormalContent()
    {
        if(StoredOriginalContent != null)
        {
            Content = StoredOriginalContent;
        }
    }
}

Тогда XAML использовать:

    <local:TestSwapContentControl x:Name="mySwitch">
            <Rectangle Height="50" Width="100" Fill="Black" />
        <local:TestSwapContentControl.FullContent>
                <StackPanel>
                    <TextBlock>1</TextBlock>
                    <TextBlock>2</TextBlock>
                    <TextBlock>3</TextBlock>
                    <TextBlock>4</TextBlock>
                    <Rectangle Height="50" Width="100" Fill="Red" />
                </StackPanel>
            </local:TestSwapContentControl.FullContent>
    </local:TestSwapContentControl>   

Со следующими cs на странице:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (myTempBool)
        {
            mySwitch.SwitchToFullContent();
            myTempBool = false;
        }
        else
        {
            mySwitch.SwitchToNormalContent();
            myTempBool = true;
        }
    }

Теперь, если вам действительно нужно сделать элемент управления полностью расширяемым другими разработчиками, вам нужно использовать visualstatemenager, но это настоящая стерва. Если вы не знаете, как настроить диспетчер визуальных состояний и состояния через generic.xaml, вот руководство:

http://scorbs.com/2008/06/11/parts-states-model-with-visualstatemanager-part-1-of/

Вот рабочий пример, но он не идеален, так как я не могу установить содержимое ContentPresenter напрямую.

using System.Windows;
using System.Windows.Controls;

namespace SilverlightTestApplication
{
    [TemplateVisualState(Name="Normal", GroupName="SizeStates")]
    [TemplateVisualState(Name="Expanded", GroupName="SizeStates")]
    public class TestVSMControl : ContentControl
    {
        public object SmallContent
        {
            get { return (object)GetValue(SmallContentProperty); }
            set { SetValue(SmallContentProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SmallContent.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SmallContentProperty =
            DependencyProperty.Register("SmallContent", typeof(object), typeof(TestVSMControl), null);

        public object LargeContent
        {
            get { return (object)GetValue(LargeContentProperty); }
            set { SetValue(LargeContentProperty, value); }
        }

        // Using a DependencyProperty as the backing store for LargeContent.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty LargeContentProperty =
            DependencyProperty.Register("LargeContent", typeof(object), typeof(TestVSMControl), null);

        public bool Pressed
        {
            get { return (bool)GetValue(PressedProperty); }
            set { SetValue(PressedProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Pressed.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty PressedProperty =
            DependencyProperty.Register("Pressed", typeof(bool), typeof(TestVSMControl), 
                new PropertyMetadata(new PropertyChangedCallback(PressedPropertyChanged)));

        static void PressedPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var me = sender as TestVSMControl;
            me.ChangeState();
        }

        public TestVSMControl()
        {
            DefaultStyleKey = typeof(TestVSMControl);
        }

        void ChangeState()
        {
            GoToState(true);
        }

        private void GoToState(bool useTransitions)
        {
            if (Pressed)
            {
                VisualStateManager.GoToState(this, "Normal", useTransitions);
            }
            else
            {
                VisualStateManager.GoToState(this, "Expanded", useTransitions);
            }
        }
    }
}

В вашем generic.xaml (включая xmlns: vsm = "clr-namespace: System.Windows; Assembly = System.Windows"):

<Style TargetType="local:TestVSMControl">        
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:TestVSMControl">
                <StackPanel>
                    <vsm:VisualStateManager.VisualStateGroups>
                        <vsm:VisualStateGroup x:Name="SizeStates">
                            <vsm:VisualState x:Name="Normal">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Content" Storyboard.TargetName="myContentPresenter" BeginTime="00:00:00" Duration="00:00:00.0010000" >
                                        <ObjectAnimationUsingKeyFrames.KeyFrames>
                                            <DiscreteObjectKeyFrame KeyTime="0:0:0">
                                                <DiscreteObjectKeyFrame.Value>
                                                    <StackPanel>
                                                        <TextBlock>Rararasputin</TextBlock>
                                                        <Button Content="{TemplateBinding SmallContent}" />
                                                    </StackPanel>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames.KeyFrames>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </vsm:VisualState>
                            <vsm:VisualState x:Name="Expanded">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Content" Storyboard.TargetName="myContentPresenter" BeginTime="00:00:00" Duration="00:00:00.0010000" >
                                         <ObjectAnimationUsingKeyFrames.KeyFrames>
                                            <DiscreteObjectKeyFrame KeyTime="0:0:0"  >
                                                <DiscreteObjectKeyFrame.Value>
                                                    <StackPanel>
                                                        <TextBlock>Other one</TextBlock>
                                                        <Button Content="{TemplateBinding LargeContent}" />
                                                    </StackPanel>
                                                </DiscreteObjectKeyFrame.Value>
                                            </DiscreteObjectKeyFrame>
                                        </ObjectAnimationUsingKeyFrames.KeyFrames>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </vsm:VisualState>
                        </vsm:VisualStateGroup>
                    </vsm:VisualStateManager.VisualStateGroups>                        
                    <ContentPresenter x:Name="myContentPresenter" />
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

А как использовать на своей странице:

            <local:TestVSMControl x:Name="myVSMControl" Height="200">
                <local:TestVSMControl.SmallContent>
                    <Rectangle Height="50" Width="100" Fill="Red" />
                </local:TestVSMControl.SmallContent>
                <local:TestVSMControl.LargeContent>
                    <Rectangle Height="50" Width="100" Fill="Green" />
                </local:TestVSMControl.LargeContent>        
            </local:TestVSMControl>
            <Button Content="Swap" x:Name="VSMButton" Click="VSMButton_Click"  />

со следующим на вашей странице:

    private void VSMButton_Click(object sender, RoutedEventArgs e)
    {
        myVSMControl.Pressed = !myVSMControl.Pressed;
    }
1 голос
/ 29 марта 2009

Если вы говорите о диспетчере состояний Silverlight Visual, боюсь, это невозможно.

VisualStates содержат только объекты Storyboard, которые, в свою очередь, содержат анимацию. Насколько я знаю, вы не можете изменить шаблон с ним.

Я не уверен в возможностях WPF VisualStateManager.

...