user4633966
user4633966

Reputation:

WPF MVVM binding with specific types

I'm trying to implement the MVVM design pattern in my WPF application but I have some problems to bind my Views with my ViewModels.

In one of my ViewModels, I have the following property :

public IPEndPoint EndPoint
{
    get { return _serverInfos.EndPoint; }
    private set
    {
        _serverInfos.EndPoint = value;
        RaisePropertyChanged("EndPoint");
    }
}

I want to bind this property in the related View like that :

<TextBox Text="{Binding EndPoint.Address}" />
<TextBox Text="{Binding EndPoint.Port}" />

The EndPoint.Port binding works as expected but the other one doesn't because EndPoint.Address is not a string (it's an IPAddress). Of course, I could define two string properties instead of one IPEndPoint but I think that it's not a good solution.

I also have the same problem using Enums when I want to convert them into int :

<ComboBox SelectedIndex="{Binding MyEnumProperty}" />

How could I solve these problems ?

Thank you for your help.

Upvotes: 2

Views: 1841

Answers (3)

Szabolcs D&#233;zsi
Szabolcs D&#233;zsi

Reputation: 8843

A converter you can use for converting between IPAddress and string.

public class IPAddressConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var ipAddress = value as IPAddress;

        if (ipAddress != null)
        {
            return ipAddress.ToString();
        }

        return DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var text = value as string;
        IPAddress ipAddress;

        if (text != null && IPAddress.TryParse(text, out ipAddress))
        {
            return ipAddress;
        }

        return DependencyProperty.UnsetValue;
    }
}

And then in a ResourceDictionary or a Resources collection of a FrameworkElement

<IPAddressConverter x:Key="IpAddressConverter" />

And in the binding:

<TextBox Text="{Binding EndPoint.Address, Converter={StaticResource IpAddressConverter}}" />

Upvotes: 3

NextInLine
NextInLine

Reputation: 2204

Normally you want a view model to take things from the model and expose them in a way that the view can consume. As such

  1. MyEnumProperty should be an System.Int32 (int) for ComboBox.SelectedIndex to consumer
  2. You should probably implement two separate properties for EndPointPort and EndPointAddress, and EndPointAddress should be a string that converts to an IPAddress when working with the model

You can use IValueConverters for both of those, but then you are reducing some of the utility of a separate view model in the first place if all it does is act like the model.

Upvotes: 2

karfus
karfus

Reputation: 939

As far as the IPEndPoint type, this is a perfect case for a type converter (IValueConverter). It would look something like this, assuming your type has a valid ToString implementation:

public class IPEndPointConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        IPEndPoint endPoint = (IPEndPoint)value;
        return endPoint.ToString();
    }

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

You could then add the converter to your XAML file with a ResourceDictionary as follows (assuming you've added the relevant namespace, here called "converters", to your XAML):

<Window.Resources>
    <converters:IPEndPointConverter x:Key="ipEndPointConverter" />
</Window.Resources>

You would then simply use this anywhere you need it within your XAML by adding it to the binding:

<TextBox Text="{Binding Path=EndPoint.Address, Converter={StaticResource ResourceKey=ipEndPointConverter}}" />

Upvotes: 0

Related Questions