0

My view has 2 buttons called BrowseButton and UploadButton.

BrowseButton is default and UploadButton is not. My goal is for the default to change after BrowseButton is clicked (ie BrowseButton is not default but UploadButton is).

When BrowseButton is clicked, a Property (string) in my ViewModel is set. This means I can bind to that property and pass the value of that property to my IValueConverter and return either a true or false. This works as desired.

My BoolConverter looks like

 public class BoolConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value == null || string.IsNullOrEmpty(System.Convert.ToString(value)))
                return false;

            return true;
        }

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

And my Xaml

<Button Content="Browse for file" Width="150" Margin="5" Command="{Binding BrowseForFileCommand}" IsDefault="{Binding File, Converter={StaticResource BConverter}}" />
<Button Content="Upload" Width="75" Margin="5" Command="{Binding UploadCommand}"  IsDefault="{Binding File, Converter={StaticResource BConverter}}" />

The problem is, they both bind to the same BoolConverter class and as such are both equal (ie if one is false then both are false!). Again, I can understand why.

My question is, how do I get around this? Is it really just a case of having multiple Converter classes?

EG

public class BoolConverterForThis : IValueConverter
{//implementation}
public class BoolConverterForThat : IValueConverter
{//implementation}
public class BoolConverterForOther : IValueConverter
{//implementation}
Phil
  • 42,255
  • 9
  • 100
  • 100
Dave
  • 8,163
  • 11
  • 67
  • 103
  • why not define two bool properties in your viewmodel like `CanUpload`,`CanBrowse` and bind to the directly?? – Akram Berkawy Mar 09 '13 at 15:21
  • I did think of this, but it felt wrong to use the ViewModel for a UI function; I felt the ViewModel should hold data only. Is this wrong? – Dave Mar 09 '13 at 15:22

2 Answers2

1

I would be tempted to do something like this:

public class StringIsEmptyToBoolConverter : MarkupExtension, IValueConverter
{
    public StringIsEmptyToBoolConverter()
    {
        this.Result = false;
    }

    public bool Result { get; set; }

    public object Convert(object value, Type targetType, 
                          object parameter, CultureInfo culture)
    {
        return string.IsNullOrEmpty(value as string) ? this.Result : !this.Result;
    }

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

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}

which you could use in you Xaml like this:

<Window.Resources>
    <wpfApplication2:StringIsEmptyToBoolConverter 
        x:Key="TrueResultConverter" Result="True"/>
    <wpfApplication2:StringIsEmptyToBoolConverter 
        x:Key="FalseResultConverter" Result="False"/>
</Window.Resources>
<Grid>
    <!-- because the converter derives from MarkupExtension you can 
         create an instance directly instead of creating a resource -->
    <Button IsDefault="{Binding File,
          Converter={wpfApplication2:StringIsEmptyToBoolConverter Result=True}}"/>

    <!-- or use a resource -->
    <Button IsDefault="{Binding File, 
          Converter={StaticResource TrueResultConverter}}"/>
    <Button IsDefault="{Binding File, 
          Converter={StaticResource FalseResultConverter}}"/>
</Grid>
Phil
  • 42,255
  • 9
  • 100
  • 100
  • Thank you Phil. I like this because of it's re-use, I've learned something and, it works perfectly! Thank you. – Dave Mar 09 '13 at 16:15
  • Further reading on MarkupExtension if helpful to anyone: http://msdn.microsoft.com/en-gb/library/ms747254.aspx – Dave Mar 09 '13 at 16:24
  • based upon your answer, can I assume it is typical to have multiple Converter classes (instead of trying to create 1 'God-like' class to handle everything)? – Dave Mar 13 '13 at 10:23
  • 1
    Yes, usually lots of converters. – Phil Mar 13 '13 at 14:40
  • Phil, thank you for taking the time, this has helped make a few things that little bit clearer! :) – Dave Mar 13 '13 at 14:47
0

I had the same problem and I had to resort to coding a True Visibility converter and False Visiility converter. Not that you can't code a visibility converter, but for the benefit of someone who doesn't, this is what my code looked like.

public class TrueVisibilityConverter : IValueConverter
{
    public object Convert(
        object value,
        Type targetType,
        object parameter,
        CultureInfo culture)
    {
        bool visibility = (bool)value;
        return visibility ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(
        object value,
        Type targetType,
        object parameter,
        CultureInfo culture)
    {
        Visibility visibility = (Visibility)value;
        return (visibility == Visibility.Visible);
    }
}



public class FalseVisibilityConverter : IValueConverter
    {
        public object Convert(
            object value,
            Type targetType,
            object parameter,
            CultureInfo culture)
        {
            bool visibility = (bool)value;
            return visibility ? Visibility.Collapsed:Visibility.Visible ;
        }

        public object ConvertBack(
            object value,
            Type targetType,
            object parameter,
            CultureInfo culture)
        {
            Visibility visibility = (Visibility)value;
            return (visibility == Visibility.Collapsed);
        }
    }
Dave
  • 8,163
  • 11
  • 67
  • 103
VenVig
  • 645
  • 1
  • 10
  • 14