开发者

ComboBox.Text not taking the ItemStringFormat property into account

I just noticed a strange behavior which looks like a bug. Consider the following XAML :

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:sys="clr-namespace:System;assembly=mscorlib">
  <Page.Resources>
    <x:Array x:Key="data" Type="{x:Type sys:String}">
        <sys:String>Foo</sys:String>
        <sys:String>Bar</sys:String>
        <sys:String>Baz</sys:String>
    </x:Array>
  </Page.Resources>
  <StackPanel Orientation="Vertical">
      <Button>Boo</Button>
      <ComboBox Name="co开发者_如何学编程mbo" ItemsSource="{Binding Source={StaticResource data}}" ItemStringFormat="##{0}##" />
      <TextBlock Text="{Binding Text, ElementName=combo}"/>
  </StackPanel>
</Page>

The ComboBox displays the values as "##Foo##", "##Bar##" and "##Baz##". But the TextBlock displays the selected values as "Foo", "Bar" and "Baz". So the ItemStringFormat is apparently ignored for the Text property...

Is that a bug ? If it is, is there a workaround ?

Or am I just doing something wrong ?


It's not a bug: ItemStringFormat is just a shortcut for "data template having a textblock bound to the value with the specified string format set in the binding". Text however is generally used when IsEditable is true and represents user-input. When you have anything other than strings in your list, it's preferable to use the SelectedItem than the Text. In any case, the following code will reapply the format to the text:

<TextBlock Text="{Binding ElementName=combo, Path=Text, StringFormat='##{0}##'}"/>


I know this is probably too late to help the OP, but just in case someone else stumbles across this...

The solution I would use to the real problem that the OP mentioned in the comment to the other answer is to use an IValueConverter.

Here's the code for the FormatConverter class:

public class FormatConverter : System.Windows.Data.IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string format = parameter.ToString();
        return string.Format(format, value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

And here's how you use it (taken from the question with modification):

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:sys="clr-namespace:System;assembly=mscorlib"
  xmlns:local="clr-namespace:YourNamespace">
  <Page.Resources>
    <x:Array x:Key="data" Type="{x:Type sys:String}">
      <sys:String>Foo</sys:String>
      <sys:String>Bar</sys:String>
      <sys:String>Baz</sys:String>
    </x:Array>
    <local:FormatConverter x:Key="FormatConverter" />
  </Page.Resources>
  <StackPanel>
    <ComboBox ItemsSource="{Binding Source={StaticResource data}}" ItemStringFormat="##{0}##"
              Text="{Binding Path=VMProp, Mode=OneWayToSource, Converter={StaticResource FormatConverter}, ConverterParameter=##{0}##}" />
  </StackPanel>
</Page>

This would cause the items to show up in the ComboBox as "##Foo##", "##Bar##", and "##Baz##" thanks to the ItemStringFormat being set to "##{0}##". Plus the VMProp property on the ViewModel would be assigned the values in the same format when they are selected thanks to the FormatConverter with the ConverterParameter being set to "##{0}##".

Please note that even though I used the ComboBox.Text property to remain consistent with the original question, I would suggest that the ComboBox.SelectedItem property would be more appropriate. ;)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜