2014-09-11 162 views
3

我正在開發一款使用相機拍攝自動照片的軟件。我希望用戶能夠設置照片間隔。我希望看起來像一些旋轉木馬一樣工作。WPF旋轉木馬/旋轉元件

這是它應該是什麼樣子:

當我刷卡(或用鼠標拖動),應該在給定方向移動:

所選項目應始終中間,如果它是最後一個,第一個應該向右旋轉(反之亦然)。

我已經添加了基本的滑動/拖動功能,它可以識別何時執行了操作以及在哪個方向上。 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元素會更好嗎?

+0

你簽出任意[現有轉盤]的(http://wpfcarousel.codeplex.com/)控制可在那裏了嗎?可以爲你節省一些麻煩。 – 2014-09-11 13:58:32

+1

是的,我已經檢查了一個。我想自己創建它,因爲我想在過程中學習一些東西。 – 2014-09-11 14:11:11

回答

2

我基於自己上面聲明的樣式,但未包含在代碼中。您可以在純xaml和視圖模型中執行此操作。這將是一個非常簡單粗暴的例子。或者,您可以實現一個自定義控件,該控件繼承某個類的層次結構,而不是控制哪個默認cust控件模板提供的默認值。我建議您查看MVVM模式和Galaxoft 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> 

視圖模型 Remeber設置此作爲的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

+3

謝謝Stian :)我其實想過使用ListView,雖然沒有嘗試,但因爲還有另一個問題我正在面對:如何使ListView無限(或循環)。我想達到的目的是讓選中的項目始終顯示在中心,並且圍繞它的其他元素循環播放。如我的兩張圖片所示,選擇「10s」時「3s」向右移動。 我是否需要重新排序集合中的元素並重新繪製ListView,或者是否有更好的方法呢? – 2014-09-12 11:06:44

+2

@DavideDeSantis您可能需要創建自己的項目面板,我在第一個Microsoft Surface(大表格)上編寫了學士論文編碼。事實上,與您的問題幾乎完全相同,但我無法分享此代碼,因爲它屬於我撰寫論文的公司。基本上,您可以創建一個面板,並在控制模板的面板上設置ItemsHost = true。 [這個例子已經過時了,因爲Dr.WPF在2010年停止了對WPF的編碼](http://drwpf.com/blog/category/panels/),但它可能會指向你正確的方向。您將需要實現IScrollInfo接口。 – 2014-09-12 15:19:56

+1

這看起來不錯,謝謝。我會研究它:) – 2014-09-13 06:22:25