2011-10-15 65 views
0

我想顯示一個列表框,其中的項目在選中時將顯示一個按鈕,該按鈕對所選數據項目執行特定操作。爲此,我使用兩個數據模板,一個是NormalTemplate(它沒有按鈕),另一個是SelectedTemplate(它有一個按鈕,其Tag屬性綁定到數據,用於按鈕單擊事件處理程序)。選擇Listbox中的項目時,我想分配SelectedTemplate。列表框中選定項目和普通項目的不同項目模板項目

爲此,我使用了具有VisualStateManager的自定義ControlTemplate,該VisualStateManager基於VisualState選擇適當的模板(即,選擇了& Unselected)。這個解決方案的問題是我每次需要使用不同的DataTemplates時都要創建一個新的ControlTemplate。我試圖找到一個解決方案,在其中指定正常的&所選項目的模板,並使用通用代碼根據視覺狀態更改數據模板。

下面是我的,未被選定&所選項目的DataTemplate:

<DataTemplate x:Key="NormalItemTemplate"> 
     <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*" /> 
      </Grid.ColumnDefinitions> 

      <StackPanel Grid.Column="1" Margin="8,0,0,3" VerticalAlignment="Center"> 
       <TextBlock Text="{Binding Name}" FontWeight="Bold" FontFamily="Arial" FontSize="14"/> 
       <TextBlock Text="{Binding Description}" /> 
      </StackPanel> 
     </Grid> 
    </Border> 
</DataTemplate> 

<DataTemplate x:Key="SelectedItemTemplate"> 
    <Grid> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="*" /> 
       <ColumnDefinition Width="65"/> 
      </Grid.ColumnDefinitions> 

      <StackPanel Grid.Column="1" Margin="8,0,0,3"> 
       <TextBlock Text="{Binding Name}" FontWeight="Bold" FontFamily="Arial" FontSize="14"/> 
       <TextBlock Text="{Binding Description}" /> 
      </StackPanel> 

      <Border Grid.Column="2" Grid.RowSpan="2" VerticalAlignment="Stretch"> 
       <Button Content="Process" Tag={Binding} OnClick="Process_Clicked" HorizontalAlignment="Center" VerticalAlignment="Center"/> 
      </Border> 
     </Grid> 
    </Border> 
</DataTemplate> 

下面是定義自定義的控件模板,它使用VisualStateManager來顯示或隱藏相應的ContentPresenters它的ContentTemplate被分配到NormalItemTemplate & SelectedItemTemplate風格

<Style TargetType="ListBoxItem" x:Key="ActiveGamesItemContainerStyle"> 
    <Setter Property="HorizontalContentAlignment" Value="Stretch" /> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="ListBoxItem"> 
       <Grid Background="{TemplateBinding Background}"> 
        <VisualStateManager.VisualStateGroups> 
         <VisualStateGroup x:Name="CommonStates"> 
          <VisualState x:Name="Normal" /> 
         </VisualStateGroup> 

         <VisualStateGroup x:Name="SelectionStates"> 
          <VisualState x:Name="Unselected"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SelectedContentPresenter" Storyboard.TargetProperty="Visibility"> 
             <DiscreteObjectKeyFrame KeyTime="0"> 
              <DiscreteObjectKeyFrame.Value> 
               <Visibility>Collapsed</Visibility> 
              </DiscreteObjectKeyFrame.Value> 
             </DiscreteObjectKeyFrame> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="UnSelectedContentPresenter" Storyboard.TargetProperty="Visibility"> 
             <DiscreteObjectKeyFrame KeyTime="0"> 
              <DiscreteObjectKeyFrame.Value> 
               <Visibility>Visible</Visibility> 
              </DiscreteObjectKeyFrame.Value> 
             </DiscreteObjectKeyFrame> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </VisualState> 

          <VisualState x:Name="Selected"> 
           <Storyboard> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SelectedContentPresenter" Storyboard.TargetProperty="Visibility"> 
             <DiscreteObjectKeyFrame KeyTime="0"> 
              <DiscreteObjectKeyFrame.Value> 
               <Visibility>Visible</Visibility> 
              </DiscreteObjectKeyFrame.Value> 
             </DiscreteObjectKeyFrame> 
            </ObjectAnimationUsingKeyFrames> 
            <ObjectAnimationUsingKeyFrames Storyboard.TargetName="UnSelectedContentPresenter" Storyboard.TargetProperty="Visibility"> 
             <DiscreteObjectKeyFrame KeyTime="0"> 
              <DiscreteObjectKeyFrame.Value> 
               <Visibility>Collapsed</Visibility> 
              </DiscreteObjectKeyFrame.Value> 
             </DiscreteObjectKeyFrame> 
            </ObjectAnimationUsingKeyFrames> 
           </Storyboard> 
          </VisualState> 
         </VisualStateGroup> 
        </VisualStateManager.VisualStateGroups> 

        <ContentPresenter 
           x:Name="SelectedContentPresenter" 
           Content="{TemplateBinding Content}" 
           ContentTemplate="{StaticResource NormalItemTemplate}" 
           HorizontalAlignment="Stretch" 
           Margin="{TemplateBinding Padding}" 
           Visibility="Collapsed"/> 

        <ContentPresenter 
           x:Name="UnSelectedContentPresenter" 
           Content="{TemplateBinding Content}" 
           ContentTemplate="{StaticResource SelectedItemTemplate}" 
           HorizontalAlignment="Stretch" 
           Margin="{TemplateBinding Padding}" 
           Visibility="Visible"/> 
       </Grid> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

此解決方案的問題是:

  1. 對於每個需要使用不同DataTemplates的新ListBoxItem,我需要使用與上面相同的ControlTemplate創建樣式,但只需更改ContentPresenter的ContentTemplate。因此,很多重複的代碼/ XAML。

  2. 因爲我正在使用SelectedItemTemplate中的按鈕,所以我需要在定義Click事件處理程序的相同UserControl類中定義樣式。如果UserControl使用多個ListBox,則會爲每個ListBoxes聲明一個巨大的Style定義。

我試圖解決這個問題,使用附加的屬性,但它不工作。至於,我無法得到選定的ListBoxItem(而是我得到的綁定數據)。這個想法是讓ListBoxItem獲得它的ContentPresenter並將它的ContentTemplate設置爲SelectedItemTemplate。

有沒有更好的方法來做到這一點?

感謝&問候, 蘇尼爾

回答

1

無需兩個獨立的模板,只需使用一個和使用DataTrigger切換知名度。

  1. 創建一個有IsSelected屬性的物品的視圖模型。添加NotifyPropertyChanged事件。

  2. 設置ItemContainerStyleListBoxItem.IsSelected屬性綁定到您的視圖模型上的IsSelected屬性。

  3. 然後在你的DataTemplateDataTrigger改變按鈕的VisibilityIsSelectedTrue

有關如何做到上面的例子,看看在answer to this StackOverflow question.

+1

你怎麼會在Windows Phone的做到這一點(沒有Datatriggers) –