【问题标题】:Expander Header text binding not respecting the string formatter扩展器标题文本绑定不尊重字符串格式化程序
【发布时间】:2014-06-01 02:13:40
【问题描述】:

我的项目中有一个 WPF 扩展器。我已将样式应用于扩展器以更改标题颜色等。这样做之后,我的数据仍然绑定到 Header 的内容区域,但它只是绑定了原始数据,而不是我指定的格式。请参阅下面的示例。

<Style x:Key="ValkyrieStyleExpander" TargetType="{x:Type Expander}">
   <!-- Ommiting property setters for brevity -->
   <Setter Property="HeaderTemplate">
       <Setter.Value>
            <DataTemplate>
                <TextBlock Text="{Binding}" FontWeight="Bold" 
                           Foreground="White" VerticalAlignment="Center" />
            </DataTemplate>
        </Setter.Value>
   </Setter>
</Style>

这是具有适当绑定语法的实际声明

<Expander Style="{StaticResource ValkyrieStyleExpander}" 
           Margin="10,10,0,0" 
           Width="670" 
           Header="{Binding PolicyNumber, StringFormat=Policy {0}}">
</Expander>

我运行应用程序时,标题应显示“Policy 123456”,并且在我重新设置扩展器的样式之前它已经这样做了。但是现在当我运行应用程序时,标题只显示“123456”。在数据绑定方面,我仍然是一个婴儿,所以我不确定我需要做些什么才能让新样式显示正确的数据。希望答案不是将其添加到 ValkyrieStyleExpender 的 Header Template 样式中,因为这会破坏拥有样式的目的(并非项目中的所有扩展器都用于显示特定策略)

【问题讨论】:

  • 你能举一个例子,它没有样式(因为通常StringFormat永远不应该在Expander.Header属性的绑定中工作)? StringFormat 仅适用于类型为 string 的属性。
  • PolicyNumber 的类型是 string?
  • @Rohit,是的,策略编号是视图模型上的字符串属性。
  • @fmunkert,刚刚从扩展器中删除了样式声明,它对我有用
  • 不确定你编辑了什么,@Andy G,但恭喜你选择了一个很棒的图标,哈哈。

标签: wpf data-binding expander


【解决方案1】:

StringFormatExpander.Header 属性中使用它时通常不起作用,因为该属性是not of type string

您需要编写自己的从IFormatter 派生的类,该类实现您在属性中实际定义的格式化字符串。我研究了很多,没有找到更好的解决方案。

该类可能如下所示:

public class SomeClass: IFormattable
{
    public string ToString(string format, IFormatProvider formatProvider)
    {
        if(format == "n")
        {
            return "This is the formatted string";
        }
        else
        {
            return "this is the non-formatted string";
        }
    }
}

你会以这种方式在你的风格中使用它:

Setter Property="HeaderStringFormat" Value="n" />

【讨论】:

  • 你确定这会起作用吗?根据 MSDN 文档,如果设置了 HeaderTemplate 属性(如 OP 的样式),则忽略 HeaderStringFormat。 (请参阅msdn.microsoft.com/en-us/library/… 中的“备注”部分)。
  • @fmunkert 不,我不确定,感谢您指出这一点。如果真的不可能用一种风格来做,他可能会考虑放弃这种风格。不是一个优雅的解决方案,但它虽然有效。
  • @Mostey,您正在链接到德语文档。 OP 在加利福尼亚,德语文档可能不是很有帮助。
  • @GayotFow MSDN 会自动为我显示英文翻译,尽管它是德文链接。但是,我更新了链接。
  • 谢谢@mostey。我很欣赏这方面的想法和研究。从纯粹主义者的角度来看,我会厌倦需要更改视图模型以适应视图的解决方案。理想情况下,我想让他们俩都不知道对方。
【解决方案2】:

如果字符串格式不适合你,你可以轻松实现一个转换器,比如...

#region PolicyConverter (ValueConverter)
public class PolicyConverter : MarkupExtension, IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            return "Policy " + value.ToString();
        }
        return null;
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}
#endregion

...然后在您的 Xaml...

中声明它
<Window.Resources>
    <pc:PolicyConverter x:Key="PolicyConverter"/>
</Window.Resources>

...最后在您的模板中引用它。我没有使用(或修改)您的 ValkyrieStyleExpander 代码。但是为了验证这种方法的正确性,我使用了下面的声明作为函数原型……

    <Expander Name="Expander1">
        <Expander.HeaderTemplate>
            <DataTemplate>
                <TextBlock 
                    Text="{Binding ElementName=Expander1, 
                    Path=DataContext.PolicyNumber, 
                    Converter={StaticResource PolicyConverter}}"/>
            </DataTemplate>
        </Expander.HeaderTemplate>
    </Expander>

...它按预期工作(.net 4.5)。如果您需要将内联模板转移到 Xaml 中的全局声明中,这也是一个很好的起点。

【讨论】:

  • 嗨@Gayot fow,不幸的是我无法在扩展器标题模板中指定确切的格式化程序,因为我需要在其他扩展器上重用该样式。但是您的回答让我想起了另一个问题:即我可以在实现样式的特定扩展器中覆盖样式吗?我回家后必须测试一下。
猜你喜欢
  • 2018-02-14
  • 2016-05-08
  • 2011-10-11
  • 1970-01-01
  • 2018-02-28
  • 2014-10-14
  • 2018-11-05
  • 2021-11-28
  • 2011-04-27
相关资源
最近更新 更多