views:

1642

answers:

4

When binding with Wpf is there a way to use System.String funcntions without using converters?

<TextBlock Text="({Binding Path=Text}).Trim()"/>

that's basically my desire.

+4  A: 

I would use a converter.

Binding Xaml

<StackPanel>
  <StackPanel.Resources>
    <local:StringTrimmingConverter x:Key="trimmingConverter" />
  <StackPanel.Resources>
  <TextBlock Text="{Binding Path=Text, Converter={StaticResource trimmingConverter}}" />
</StackPanel>

StringTrimmingConverter.cs

using System;
using System.Windows.Data;

namespace WpfApplication1
{
    [ValueConversion(typeof(string), typeof(string))]
    public class StringTrimmingConverter : IValueConverter
    {
        #region IValueConverter Members
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value.ToString().Trim();
        }
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return value;
        }
        #endregion
    }
}

And if VB StringTrimmingConverter.vb

Imports System.Globalization

Public Class StringTrimmingConverter
    Implements IValueConverter

    Public Function ConvertBack(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.ConvertBack
        Return value.ToString().Trim
    End Function

    Public Function Convert(ByVal value As Object, ByVal targetType As Type, ByVal parameter As Object, ByVal culture As CultureInfo) As Object Implements IValueConverter.Convert
        Return value
    End Function

End Class
bendewey
I said that I don't want to have milion converters, therefore I asked the question, I started to careate an ultimate string converter, look bellow, tell me your opinion about, looking for improvements (especially parameter addressing).Thanks a lot anyway!
Shimmy
I don't know why people get so afraid of having a million converters. just put them in a folder and make sure thier well named. It fits right in with the Single Responsibility Principle (SRP) principle.
bendewey
I donno, I personally hate it, not only but, I put all my converters in a namespace 'converters' and they're all in the same file.with today's VS navigation I don't have any problems.anyway, thanks for your post.
Shimmy
A: 

I created an ultimate converter for all the functions in System.String, needs some improvement would love to hear from you, hope to update it in future, please accept:

    <ValueConversion(GetType(String), GetType(String))> _
Class StringFunctions : Implements IValueConverter
    Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
        If parameter Is Nothing OrElse Not TypeOf parameter Is String OrElse String.IsNullOrEmpty(parameter) Then Return Nothing
        Dim parameters As New List(Of String)(parameter.ToString.Split(":"c))
        parameter = parameters(0)
        parameters.RemoveAt(0)
        If String.IsNullOrEmpty(parameter) Then Return value

        Dim method = (From m In GetType(String).GetMethods _
                Where m.Name = parameter _
                AndAlso m.GetParameters.Count = parameters.Count).FirstOrDefault
        If method Is Nothing Then Return value
        Return method.Invoke(value, parameters.ToArray)
    End Function
    Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Throw New NotSupportedException
    End Function
End Class

The in the binding, when u use a converter u have an option to pass a parameter to the converter (Binding.ConverterParameter) pass all your parameters seperated with : (colon - you can change it in the String.Split delimiter parameter), while the first parameter is the function name, the function will count the extra parameters and try to pass it.
I still didn't work on the parameters addressing, it's a shallow function.

Would like to see your improvements and notes.
thanks. Shimmy

Shimmy
Whoa! Use the code feature in the editor to keep your code formatted. Works best if you paste the code then press the button.
Matt Olenik
Sorry I saw it, it's now formatted :)
Shimmy
I would suggest generalising this to call a method on any object type. There is nothing special about the use of String. In fact, the attribute "[ValueConversion(typeof(string), typeof(string))]" is already incorrect for a call to split as it does not return a String!
Daniel Paull
You're right, the output type attribute should be declared as Object.Thanks
Shimmy
A: 

You will need to use a converter as you want to transform the data your control is bound to. To avoid writing lots of converters simple transformations, you can use the Dynamic Language Runtime and write expressions in your favourite DLR scripting language (such as Python, Ruby, etc).

See my blog series for an example of how to achieve this. Part 3 talks specifically about ValueConverters.

Daniel Paull
A: 

I created an ultimate converter for all the functions in System.String, needs some improvement would love to hear from you, hope to update it in future, please accept:

VB:

<ValueConversion(GetType(String), GetType(Object))> _
Class StringFunctions : Implements IValueConverter
    Public Function Convert(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
        If parameter Is Nothing OrElse Not TypeOf parameter Is String OrElse String.IsNullOrEmpty(parameter) Then Return Nothing
        Dim parameters As New List(Of String)(parameter.ToString.Split(":"c))
        parameter = parameters(0)
        parameters.RemoveAt(0)
        If String.IsNullOrEmpty(parameter) Then Return value

        Dim method = (From m In GetType(String).GetMethods _
                Where m.Name = parameter _
                AndAlso m.GetParameters.Count = parameters.Count).FirstOrDefault
        If method Is Nothing Then Return value
        Return method.Invoke(value, parameters.ToArray)
    End Function
    Public Function ConvertBack(ByVal value As Object, ByVal targetType As System.Type, ByVal parameter As Object, ByVal culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
        Return value.ToString()
    End Function
End Class

C#: -converted by a tool, don't rely!

 [ValueConversion(typeof(string), typeof(object))]
public class StringConverter : IValueConverter
{
    #region IValueConverter Members

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value == null) return null;
        value = value.ToString();
        if (String.IsNullOrEmpty(value as string)) return "";
        if (parameter == null || !parameter is string || String.IsNullOrEmpty((string)parameter)) return value;
        List<string> parameters = new List<string>(((string)parameter).Split(':'));
        parameter = parameters[0];
        parameters.RemoveAt(0);

        var method = (from m in typeof(String).GetMethods()
                        where m.Name== parameter 
                        && m.GetParameters().Count()==parameters.Count
                            select m).FirstOrDefault();
        if (method == null) return value;
        return method.Invoke(value, parameters.ToArray());
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return value;
    }

    #endregion
}

Xaml:

<TextBox Text="{Binding Path=String, Converter={StaticResource StringConverter}, ConverterParameter=Trim:Argument:AnotherArgument}" />

Then, in the binding, when u use a converter u have an option to pass a parameter to the converter (Binding.ConverterParameter) pass all your parameters seperated with : (colon - you can change it in the String.Split delimiter parameter), while the first parameter is the function name, the function will count the extra parameters and try to pass it.
I still didn't work on the parameters addressing, it's a shallow function.

Would like to see your improvements and notes.
thanks. Shimmy

Shimmy