如何使用VisualStateManager更改ListBoxItem的文本颜色(前景)?

4
这是问题所在。我可以创建一个ListBox并对其进行样式设置。我可以编辑模板的副本,使状态在Expression Blend 3中可用。当选定时,我可以更改状态,以便修改行项目的背景颜色。但是由于ContentPresenter,我无法更改文本的前景色!是否有任何示例XAML可以展示如何完成这个看似简单的任务?
答案似乎在移除ContentPresenter并用某种ListBoxItem样式或模板替换它。但这就是我卡住的地方。ListBox的ContentPresenter引用了一些其他模板“{TemplateBinding Template}”-那在哪里?此外,当我尝试以任何方式修改ContentPresenter时,States面板会变空,我只剩下一堆XAML。幸运的是,有CTRL-Z!
我真的认为微软必须重新考虑XAML方法或使Blend成为一个更完整的工具。它应该工作的方式是我应该能够点击任何元素并为其定义状态。如果我试图打破规则,Blend应该告诉我这一点并提供修复的方法。仅仅让States面板变空并没有帮助。
3个回答

1

通常情况下,ListBox 不负责项本身的内容,包括它们使用的 Foreground 颜色(如果需要)。如果项是一系列图像,则 Foreground 是无意义的。如果项是一个复杂的多元素 UI,其中包含各种不同的文本项,每个项都需要不同的 Foreground 颜色,则 ListBox 提供单个 Foreground 颜色的想法也是无意义的。

这就是为什么默认模板为项容器使用 ContentPresenter 的原因,它基本上意味着“在此放置任意项内容”。

如果您想为列表框创建一个新样式,以用于其容器项样式,则必须接受此限制,您的 VSM 无法知道所包含项的详细信息。

但是,如果您正在为特定实例的 ListBox 创建容器样式,并且了解所呈现项的类型和性质,则不需要在模板中保留 ContentPresenter。您可以直接替换为任何 Xaml,以呈现每个项。

例如,您可以在Xaml中将ContentPresenter替换为以下内容:
<Grid Margin="{TemplateBinding Padding}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}">
    <TextBlock x:Name="ContentItem" Text="{Binding Property1, Mode=OneWay}" TextWrapping="Wrap" Foreground="#FFDC1C1C"/>
</Grid>

请注意项目的填充和水平对齐方式与演示器使用的相同。在这种情况下,我使用一个称为“ContentItem”的单个TextBlock,并将其绑定到源对象的Property1属性。
现在模板包含一个命名的TextBlock来显示该项目,我可以通过调整VSM来修改它的Foreground以适应不同的可视状态。

我用一个包含TextBlock的自定义DataTemplate替换了ContentPresenter。为了让VSM工作,当listbox触发SelectionChanged事件时,我需要以某种方式获取到实际的自定义控件实例的引用。这是有问题的。VSM.GoToState方法需要传递实例才能正常工作。我似乎无法获取到该引用。有什么想法吗?我同意你应该能够“摆弄VSM”来使其工作,但“应该”是关键词。然而,我还没有看到有人这样做。 - Newclique
现在,在控件的加载事件中,我可以将每个自定义DataTemplate实例捕获到一个数组中,然后根据父ListBox的SelectedIndex属性使用数字索引来查找实例,但这种方法很难扩展。 - Newclique
好的,我找到了一种方法来实现它,而不使用VSM,但这会消除播放动画的能力。我将TextBlock的Foreground更改为{TemplateBinding Foreground},然后在ListBoxItem上设置Foreground。唉... - Newclique
看,这很有趣。几乎没有人回应这个非常普遍的问题。这就是为什么我认为要么a)VSM并不总是实用的方法,特别是对于列表控件;要么b)它只是太复杂了,难以连接这些东西;或者c)微软需要修改对象模型/树,以便公开通过自定义模板附加的项目。我在这里找到了一篇非常有趣的文章(http://blog.avanadeadvisor.com/blogs/markti/archive/2008/05/03/11060.aspx),它很有前途。 - Newclique

1

非常抱歉挖掘一个老问题,但我也遇到了同样的问题并找到了解决方案。我会分享它,谁知道呢,它可能对某人有用。

解决方法非常简单:如果您在模板中将ContentPresenter替换为ContentControl,则可以解决问题(ContentControl具有Foreground属性)。


0

哦,太棒了!感谢您的反馈。我想我最终创建了一个用户控件并公开了一个前景属性来设置颜色,但我记不清了。您的答案与之前的答案结合起来真的很有帮助。

顺便说一下,我确实学会了使用依赖属性和整个9码制作自己的自定义控件,让我告诉你,这真的非常值得。我感觉现在可以用WPF/SL做任何事情。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接