Windows Phone 7 - 为所选 ListBoxItem 中的特定控件设置样式 [英] Windows Phone 7 - Setting style for specific control within selected ListBoxItem

查看:13
本文介绍了Windows Phone 7 - 为所选 ListBoxItem 中的特定控件设置样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有这样的事情:

<Grid>
    <ListBox x:Name="list" 
        ItemsSource="{Binding SomeCollection, Mode=TwoWay}" 
        SelectedItem="{Binding SomeItem, Mode=TwoWay}">                    
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock x:Name="first" Text="{Binding SomeProperty}" />
                <TextBlock x:Name="second" Text="{Binding OtherProperty}" />
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

现在,当 ListBoxItem 被选中时,我如何更改名为second"的 TextBlock 的某些样式属性(例如 FontSize)?如果我想为所有 ListBoxItem 的内容设置 FontSize,那么我没有问题.该场景在这里和网络上的其他地方都有很好的记录.

Now, how do i alter some style property (f.ex. FontSize) of only the TextBlock called "second" when a ListBoxItem gets selected? If i'd like to set the FontSize for all ListBoxItem's contents, then i'd have no problem. That scenario is quite well documented here and elsewhere on the web.

推荐答案

我不会给你一个确切的解决方案,但是一个好的开始:查看文件

I will not give you an exact solution, but a good point to start with: check out the file

C:Program FilesMicrosoft SDKsWindows PhonevX.YDesignSystem.Windows.xaml

您必须将 X.Y 与您的设置一起调整为 7.0/7.1.在那里您会发现与 WP7/Silverlight 的所有基本 UI 控件完全相同的控件模板.在 VisualStudio 中打开它——或者其他任何东西并搜索:

you have to adjust X.Y to 7.0/7.1 along with your setup. There you will find exactly the same Control-Templates that are being used all the basic UI Controls of the WP7/Silverlight. Open it in VisualStudio-or-whateverelse and search for:

<Style TargetType="ListBoxItem">
  (... and immediatelly following ~40 lines of xaml)

嗯,既然我已经打开了那个文件,那就是这个

ah well, since I've opened that file, here's that

    <!--x:Key="PhoneListBoxItem"-->
    <Style TargetType="ListBoxItem">
      <Setter Property="Background" Value="Transparent"/>
      <Setter Property="BorderThickness" Value="0" />
      <Setter Property="BorderBrush" Value="Transparent" />
      <Setter Property="Padding" Value="0" />
      <Setter Property="HorizontalContentAlignment" Value="Left"/>
      <Setter Property="VerticalContentAlignment" Value="Top"/>
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="ListBoxItem">
            <Border x:Name="LayoutRoot" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
              <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                  <VisualState x:Name="Normal"/>
                  <VisualState x:Name="MouseOver" />
                  <VisualState x:Name="Disabled">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Background">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TransparentBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <DoubleAnimation Storyboard.TargetName="ContentContainer" Storyboard.TargetProperty="Opacity" Duration="0" To=".5" />
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
                <VisualStateGroup x:Name="SelectionStates">
                  <VisualState x:Name="Unselected"/>
                  <VisualState x:Name="Selected">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentContainer" Storyboard.TargetProperty="Foreground">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneAccentBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>
              <ContentControl x:Name="ContentContainer" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
                Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Foreground="{TemplateBinding Foreground}" />
            </Border>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

这是您的 DEFAULT ListBoxItem 的完整样式 - 您想要更改的内容.浏览代码并注意 'ContentPresenter' 和前面的 'VisualStateGroup x:Name="SelectionStates"'.

This is the complete style for your DEFAULT ListBoxItem - the thing you want to alter. Skim through the code and note the 'ContentPresenter' and preceding 'VisualStateGroup x:Name="SelectionStates"'.

ContentPresenter 是显示项目的 DataTemplate 的东西.
该组中的 VisualStates 定义了 正常 状态的更改,如果在列表元素上触发选定状态",则应该发生这种变化.
一旦选择状态"减弱,元素会自动返回未选择状态,其视觉效果也随之而来.另请注意,Unselected 视觉状态不会强制执行任何更改 - 因此它保留了您的普通 DataTemplate 样式.

ContentPresenter is the thing that will show your DataTemplate for the item.
VisualStates in that group define the changes from the normal state that should occur if a "selected state" is fired of on an list element.
Once the "selection state" diminishes, the element returns to the unselected state automatically and his visuals follow. Note also that the Unselected visual state does not enforce any changes - so it preserves your plain DataTemplate style.

最后要注意的是,这是 ListBoxItem 的样式,不是您的数据项,也不是您的数据模板.您的 DataTemplate 从未被触及,它由 ContentPresenter 直接显示.ListBox 将您的所有项目包装在ListBoxItem"实例中,然后显示这些 ListBoxItem 并将该样式应用于它们.

The last thing to notice is that this is a style for ListBoxItem, and not for your data-item, nor your data-template. Your DataTemplate is never touched, it is directly displayed by the ContentPresenter. The ListBox wraps all your items in "ListBoxItem" instances, then displays those ListBoxItems and applies that style to them.

恕我直言,这是您必须处理的重点.

IMHO, this is the point you will have to work with.

您可能希望根据需要复制和更改此样式,然后将您的 ListBox.ItemContainerStyle 设置为该 样式.其中一种方法是:

You may want to copy&alter this style to your needs, and then set your ListBox.ItemContainerStyle to that new style. One of the ways is:

<YourPage.Resources>
    <Style x:Key="mylistboxitemoverride" .....
        ........
    </Style>
</YourPage.Resources>
...
...
<ListBox ......... ItemContainerStyle="{StaticResource mylistboxitemoverride}"
    ...
    ...
</ListBox>

现在,诀窍是修改选定的"VisualState,并使其不改变前景(这样做会重新设置两个文本框的样式!),而是一些其他仅影响一个 txbs 的属性.不幸的是,这可能更难/更丑.那时我不知道如何使它更漂亮",而不是用您的 DataTemplate 硬替换 ContentPresenter 并像这样在 VisualState 中引用您的确切叶子文本框:

Now, the trick is to modify the 'Selected' VisualState, and make it alter not the Foreground (doing that would restyle both your TextBoxes!), but some other property which will affect only one of your txbs. Unfortunatelly, that may be harder/uglier. I don't at that moment any idea how to make it "prettier" than hard-replacing the ContentPresenter with your DataTemplate and referencing your exact leaf-textbox in the VisualState like that:

    <Style .... TargetType="ListBoxItem">
      <Setter Property="Background" Value="Transparent"/>
      <Setter Property="BorderThickness" Value="0" />
      <Setter Property="BorderBrush" Value="Transparent" />
      <Setter Property="Padding" Value="0" />
      <Setter Property="HorizontalContentAlignment" Value="Left"/>
      <Setter Property="VerticalContentAlignment" Value="Top"/>
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="ListBoxItem">
            <Border x:Name="LayoutRoot" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
              <VisualStateManager.VisualStateGroups>
                <VisualStateGroup x:Name="CommonStates">
                  <VisualState x:Name="Normal"/>
                  <VisualState x:Name="MouseOver" />
                  <VisualState x:Name="Disabled">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Background">
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TransparentBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                      <DoubleAnimation Storyboard.TargetName="SECOND" Storyboard.TargetProperty="Opacity" Duration="0" To=".5" /> <!-- #### RETARGETTED -->
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
                <VisualStateGroup x:Name="SelectionStates">
                  <VisualState x:Name="Unselected"/>
                  <VisualState x:Name="Selected">
                    <Storyboard>
                      <ObjectAnimationUsingKeyFrames Storyboard.TargetName="SECOND" Storyboard.TargetProperty="Foreground"> <!-- #### RETARGETTED -->
                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneAccentBrush}"/>
                      </ObjectAnimationUsingKeyFrames>
                    </Storyboard>
                  </VisualState>
                </VisualStateGroup>
              </VisualStateManager.VisualStateGroups>

              <!-- #### INLINED YOUR DATATEMPLATE -->
              <StackPanel Orientation="Vertical"
                          Margin="{TemplateBinding Padding}"
                          DataContext="{TemplateBinding Content}">  <!-- #### careful with the bindings. the DataCtx may be needed or is spurious. do check that! -->
                <TextBlock Text="{Binding SomeProperty}" />  <!-- #### referenced from nowhere, so I removed the name -->
                <TextBlock x:Name="SECOND" Text="{Binding OtherProperty}" />
              </StackPanel>

            </Border>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

这应该几乎是您想要的,或者至少非常接近.我还没有测试过它,您可能需要修改正确的数据绑定(我已经包含了一个 DataContent=binding:Content,但这是一个快速猜测)并且您可能想要添加自己的动画.我想你现在有很多东西可以试验.玩得开心!

This should be almost what you want, or at least very close to it. I have not tested it, you may need to tinker with proper data-binding (I've included a DataContent=binding:Content, but that's a quick guess) and probably you will want to add your own animations. I think you have now tons of bits to experiment with. Have fun!

这篇关于Windows Phone 7 - 为所选 ListBoxItem 中的特定控件设置样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆