WPF旋转木马/旋转元件

时间:2014-09-11 13:42:40

标签: wpf xaml carousel

我正在开发一种使用相机拍摄自动照片的软件。我希望用户能够设置照片间隔。我希望它看起来和工作像某种旋转木马。

这应该是这样的:

当我滑动(或用鼠标拖动)时,它应该沿给定方向移动:

所选项目应始终位于中间,如果是最后一项,则第一项应向右旋转(反之亦然)。

我已经添加了基本的滑动/拖动功能,无论何时采取动作以及在哪个方向上都会识别。 Hovewer,我不知道如何实际移动物品。

目前,这些项目的定义如下:

<StackPanel x:Name="countdownContainer" Background="{StaticResource GuiSideBarBackgroundColor}" Orientation="Horizontal" HorizontalAlignment="Center">
    <TextBlock Style="{StaticResource CountdownElement}" Text="3s"/>
    <TextBlock Style="{StaticResource CountdownElementSelected}" Text="5s"/>
    <TextBlock Style="{StaticResource CountdownElement}" Text="10s"/>
</StackPanel>

我知道一些关于动画的基础知识,但我不知道如何像我需要的那样为它们制作动画。 使用其他一些控件而不是StackPanel和TextBlock元素会更好吗?

1 个答案:

答案 0 :(得分:2)

我基于您在上面声明的样式,但不包含在代码中。您可以在纯xaml和viewmodel中执行此操作。这将是一个非常简单粗暴的例子。或者,您可以实现一个自定义控件,该控件继承一个在层次结构中某处具有 Selector class 的类,而不是控制默认的cust控件模板提供的默认值,而不是我推荐的。你来看看MVVM模式和Galasoft MVVM Light。在此示例中,我排除了 touch gestures ,它们很容易实现,并且使用EventToCommand,您可以直接在vm或custcontrol *中使用它们。

<强>资源

<ItemsPanelTemplate x:Key="YourItemsPanelTemplate">
   <VirtualizingStackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>

<DataTemplate x:Key="YourDataTemplate">
    <TextBlock Style="{StaticResource CountdownElement}" Text="{Binding .}" x:Name="PART_TextBlock"/>
    <DataTemplate.Triggers>
        <DataTrigger
        Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType= {x:Type ListViewItem}},Path=IsSelected}" Value="True"> 
            <!-- Here I'm just changing your fontsize, do whatever you want here :) -->                                       
            <Setter Property="FontSize" Value="34" TargetName="PART_TextBlock"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

<Style x:Key="YourContainerStyle" TargetType="ListViewItem">
    <Setter Property="HorizontalContentAlignment" Value="Center" />
    <Setter Property="VerticalContentAlignment" Value="Bottom" />
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="BorderThickness" Value="0" />
    <Setter Property="Margin" Value="10,0,10,0" />
    <Setter Property="Padding" Value="0" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListViewItem}">
                <ContentPresenter x:Name="PART_ContentPresenter"
                                HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                Margin="{TemplateBinding Padding}"
                                Content="{TemplateBinding Content}"
                                ContentTemplate="{StaticResource YourDataTemplate}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="YourListBoxStyle" TargetType="ListBox">
    <Setter Property="ItemContainerStyle" Value="{StaticResource YourContainerStyle}"/>
    <Setter Property="ItemTemplate" Value="{StaticResource YourDataTemplate}"/>
    <Setter Property="ItemsPanel" Value="{StaticResource YourItemsPanelTemplate}"/>
</Style>

现在有你的样式,对于xaml代码,请注意我在这里绑定你的项目,并使用上述样式。

<强> XAML

<Grid>
    <ListView Background="{StaticResource  GuiSideBarBackgroundColor}" 
        Style="{StaticResource YourListBoxStyle}"
        ItemsSource="{Binding CountDownElements}"
        SelectedItem="{Binding SelectedItem, Mode=TwoWay}"/>
<Grid>

ViewModel 记得将其设置为视图的datacontext,或将代码复制到代码隐藏。

public class YourViewModel : INotifyPropertyChanged
{
    private ObservableCollection<string> countDownElements = new ObservableCollection<string> { "1s", "2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s", "10s" };
    private string selectedItem;

    public ObservableCollection<string> CountDownElements
    {
        get { return countDownElements; }
        set
        {
            if (Equals(value, countDownElements)) return;
            countDownElements = value;
            OnPropertyChanged();
        }
    }

    public string SelectedItem
    {
        get { return selectedItem; }
        set
        {
            if (value == selectedItem) return;
            selectedItem = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator] // remove if you don't have R#
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
}

<强>输出

Very simple stuff

希望它有助于或至少踢你正确的方向! :)

干杯

了Stian