2013-05-10 56 views
1

我有一個ListView,它有一個ItemTemplateSelector,它根據從服務中獲取的數據選擇一個模板。在這種情況下,它是具有讀取與未讀狀態的項目列表。選擇器在加載時工作良好,但是如何在用戶單擊該項目時更改模板?很顯然,我希望模板在用戶「讀取」數據時進行更改。Windows Store應用程序更改項目模板OnClick /動態

View.xaml:

<Page.Resources> 
    <selectors:MyItemTemplateSelector x:Key="NoteItemTemplateSelector" 
             ReadTemplate="{StaticResource MyReadTemplate}" 
             UnreadTemplate="{StaticResource MyUnreadTemplate}"/> 
</Page.Resources> 

<ListView x:Name="ListView1" 
     ItemTemplateSelector="{StaticResource MyItemTemplateSelector}"/> 

回答

1

你必須建立它到您的模板。我建議爲你的數據創建一個自定義的UserControl,當點擊/點擊/選擇時,隱藏'未讀'版本並顯示'閱讀'版本。您可以將起始狀態綁定到數據本身,也可以綁定數據的ViewModel。喜歡的東西:

<UserControl xmlns...> 
    <Grid> 
     <VisualStateManager.VisualStateGroups> 
      <VisualStateGroup x:Name="DisplayStates"> 
       <VisualState x:Name="Read"> 
        <Storyboard> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ReadContent"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <Visibility>Collapsed</Visibility> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="UnreadContent"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <Visibility>Collapsed</Visibility> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
       </VisualState> 
       <VisualState x:Name="Unread"> 
        <Storyboard> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="UnreadContent"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <Visibility>Collapsed</Visibility> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ReadContent"> 
          <DiscreteObjectKeyFrame KeyTime="0"> 
           <DiscreteObjectKeyFrame.Value> 
            <Visibility>Collapsed</Visibility> 
           </DiscreteObjectKeyFrame.Value> 
          </DiscreteObjectKeyFrame> 
         </ObjectAnimationUsingKeyFrames> 
        </Storyboard> 
       </VisualState> 
      </VisualStateGroup> 
     </VisualStateManager.VisualStateGroups> 
     <Grid x:Name:"UnreadContent"> 
      <!--What it looks like when Unread--> 
     </Grid> 
     <Grid x:Name:"ReadContent"> 
      <!--What it looks like when Unread--> 
     </Grid> 
    </Grid> 
</UserControl> 

然後,在你的用戶控件的代碼隱藏,聲明一個DependencyProperty(你可以使用代碼片段「propdp」):

public bool HasBeenRead 
{ 
    get { return (bool)GetValue(HasBeenReadProperty); } 
    set { SetValue(HasBeenReadProperty, value); OnHasBeenReadChanged(this, value); } 
} 

// Using a DependencyProperty as the backing store for HasBeenRead. This enables animation, styling, binding, etc... 
public static readonly DependencyProperty HasBeenReadProperty = 
    DependencyProperty.Register("HasBeenRead", typeof(bool), typeof(MyNewUserControl), new PropertyMetadata(false, OnHasBeenReadChanged)); 

然後,創建你的PropertyChanged方法切換視覺狀態!

private static void OnHasBeenReadChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
{ 
    if ((bool)e.NewValue) 
    { 
     VisualStateManager.GoToState(d as Control, "Read", true); 
    } 
    else 
    { 
     VisualStateManager.GoToState(d as Control, "Unread", true); 
    } 
} 

應該負荷正常,尤其是與默認值是假的,但萬一沒有,你可能需要在勾到控件的Loaded事件和的VisualState從那裏設置爲未讀。

最後,你只需要一個項目模板,因此擺脫了選擇的,只是做的事:

<ListView.ItemTemplate> 
    <DataTemplate> 
     <!-- You'll have to import the namespace. Also, assumes that the item --> 
     <!-- (or Item VM) has a "HasBeenRead" bool property --> 
     <namespacewheremycontrolis:MyReadUnreadControl HasBeenRead="{Binding HasBeenRead}"/> 
    </DataTemplate> 
</ListView.ItemTemplate> 

哦!實際上有一個更多的事情要做。您的ListView必須告訴該項目它已被選中!添加一個SelectionChanged EventHandler(它基本上會爲你生成一個)。

private void ListView_SelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    if(sender != null && sender is ListView) 
    { 
     if(e.AddedItems.Count > 0) 
      (e.AddedItems[0] as MyDataOrDataVMClass).HasBeenRead = true; 
    } 
} 

您的Data/VM類將需要實現INotifyPropertyChanged。如果您使用的是數據虛擬機,則應該已經這樣做了。

快樂編碼!

+0

對不起。當你說: 'set {SetValue(HasBeenReadProperty,value); OnHasBeenReadChanged(this,value); }' Visual Studio似乎不允許帶有這些參數的'OnHasBeenReadChanged'。 另一件事情正在發生,當選擇改變時,HasBeenRead設置器從不被調用,儘管我的Item HasBeenRead屬性設置器被調用。 此外,在該故事板上,可見性總是摺疊。這樣好嗎?感謝您的幫助! P.S.我正在使用Caliburn for MVVM,不知道它是否妨礙了... – Silva 2013-08-28 14:41:01

相關問題