2009-10-20 8 views
34

Mam kontrolę, którą chcę pokazać/ukryć, w zależności od wartości boolowskiej.WPF: jak używać 2 konwerterów w 1 wiązaniu?

Mam NegatedBooleanConverter (przełącza true na false i na odwrót) i muszę najpierw uruchomić ten konwerter. Mam BooleanToVisibilityConverter i muszę uruchomić ten konwerter po NegatedBoolConverter.

Jak mogę rozwiązać ten problem? Chcę to zrobić w XAML.

edit: this is a possible solution.

To nie wydają się działać. Najpierw konwertuje wartość z oddzielnymi konwerterami, a następnie robi coś z przekonwertowanymi wartościami.

Co potrzebne jest:

  • Konwersja wartości z pierwszego przetwornika (daje convertedValue).
  • Konwertuj przeliczoną wartość z drugim konwerterem i jest to wynik, którego potrzebuję.
+0

tak, rozwiązanie, z którym się łączysz jest prawdopodobnie najlepszym ... –

+0

Zobacz także [Połączenie wielu konwerterów w XAML] (http://stackoverflow.com/q/2607490/2032064) – Mifeet

+0

Miasto powiedziało to najlepiej [tutaj] (http://stackoverflow.com/a/8326207/526704), jego rozwiązanie pozwala łańcuchować tyle, ile chcesz, podobnie jak odpowiedź jberger'a, ale ta jest jeszcze bardziej elegancka i krótsza w realizacji – DLeh

Odpowiedz

0

Właśnie stworzył to, co ja o nazwie ReversedBooleanToVisibilityConverter w zasadzie to, co ci 2 zrobiłby dla ciebie, ale w jednym kroku.

+0

Tak, to byłoby możliwe rozwiązanie, ale wolę rozwiązanie, w którym mogę ponownie wykorzystać moje obecne konwertery bez konieczności ponownego odkrywania koła. Jeśli to rozwiązanie istnieje ... – Natrium

0

Aby rozwiązać ten konkretny problem, zamiast używać dwóch konwerterów, można napisać własny BoolToVisibilityConverter, który używa parametru ConverterParameter (jako bool), aby określić, czy negować oryginalną wartość logiczną.

+0

Tak, to byłoby możliwe rozwiązanie, ale wolę rozwiązanie, w którym mogę ponownie wykorzystać moje obecne konwertery bez konieczności wymyślania koła. Jeśli to rozwiązanie istnieje ... – Natrium

0

Osobiście chciałbym zrobić tylko jeden konwerter, który wykonuje pełną konwersję. Chyba że rozpaczliwie potrzebujesz konwerterów (takich jak negacja) w innych miejscach, łatwiej będzie je utrzymać (imo), jeśli konwersja zostanie wykonana raz, w jednym miejscu.

+1

Tak, to byłoby możliwe rozwiązanie, ale wolę rozwiązanie, w którym mogę ponownie wykorzystać moje obecne konwertery bez konieczności wymyślania koła. Jeśli to rozwiązanie istnieje ... – Natrium

0

Myślę, że możesz chcieć użyć Multiconvertera zamiast dwóch oddzielnych konwerterów. Powinieneś być w stanie ponownie wykorzystać logikę z istniejących konwerterów. Najpierw sprawdź numer this discussion.

3

W naszym projekcie wykonujemy zwykły BooleanToVisibilityConverter, wymieniony konwerter przyjmuje jeden parametr (cokolwiek, string, int, bool, cokolwiek). Jeśli parametr jest ustawiony, odwraca wynik, jeśli nie, wypluwa zwykły wynik.

public class BooleanToVisibilityConverter : IValueConverter 
{ 
    #region IValueConverter Members 

    public object Convert(object value, System.Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     bool? isVisible = value as bool?; 
     if (parameter != null && isVisible.HasValue) 
      isVisible = !isVisible; 
     if (isVisible.HasValue && isVisible.Value == true) 
      return Visibility.Visible; 
     else 
      return Visibility.Collapsed; 
    } 

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

    #endregion 
} 
+1

jak nazwać ten konwerter w Xaml? – Natrium

49

To co zrobiłem:

public class CombiningConverter : IValueConverter 
    { 
     public IValueConverter Converter1 { get; set; } 
     public IValueConverter Converter2 { get; set; } 

     #region IValueConverter Members 

     public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
     { 
      object convertedValue = Converter1.Convert(value, targetType, parameter, culture); 
      return Converter2.Convert(convertedValue, targetType, parameter, culture); 
     } 

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

     #endregion 
    } 

i nazywam go tak:

<converters:CombiningConverter x:Key="negatedBoolToVisibilityConverter" Converter1="{StaticResource NegatedBooleanConverter}" Converter2="{StaticResource BoolToVisibilityConverter}" /> 

MultiValueConverter może być również tak myślę. Może spróbuję później.

+0

To jest miłe ... – MoonKnight

23

Poszerzenie wspaniałej odpowiedzi Natrium ...

XAML

<conv:ConverterChain x:Key="convBoolToInverseToVisibility"> 
    <conv:BoolToInverseConverter /> 
    <BooleanToVisibilityConverter /> 
</conv:ConverterChain> 

Klasa

/// <summary>Represents a chain of <see cref="IValueConverter"/>s to be executed in succession.</summary> 
[ContentProperty("Converters")] 
[ContentWrapper(typeof(ValueConverterCollection))] 
public class ConverterChain : IValueConverter 
{ 
    private readonly ValueConverterCollection _converters= new ValueConverterCollection(); 

    /// <summary>Gets the converters to execute.</summary> 
    public ValueConverterCollection Converters 
    { 
     get { return _converters; } 
    } 

    #region IValueConverter Members 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return Converters 
      .Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture)); 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return Converters 
      .Reverse() 
      .Aggregate(value, (current, converter) => converter.Convert(current, targetType, parameter, culture)); 
    } 

    #endregion 
} 

/// <summary>Represents a collection of <see cref="IValueConverter"/>s.</summary> 
public sealed class ValueConverterCollection : Collection<IValueConverter> { } 
+3

Rozwiązanie tego [artykułu] (http://www.codeproject.com/KB/WPF/PipingValueConverters_WPF.aspx) zapewnia sprawdzanie typu w czasie wykonywania. –

+1

Powoduje przekazanie niewłaściwego parametru targetType do konwerterów. Przekaże docelowy parametr targetType dla wszystkich konwerterów, które nawet w scenariuszu otwierającego pytanie są nieprawidłowe. Typ "Widoczności" przekazywany jest do pierwszego konwertera, gdy parametr targetType jest w rzeczywistości "bool". – CodePB

3

W tym przypadku nie trzeba łańcuch konwertera. Potrzebujesz tylko konfigurowalnego konwertera. Jest to podobne do powyższej odpowiedzi Carla, ale wyraźnie określa wartości true i false (co oznacza, że ​​możesz używać tych samych konwerterów do konwersji ukrytych, widocznych lub zwiniętych).

[ValueConversion(typeof(bool), typeof(Visibility))] 
public class BoolToVisibilityConverter : IValueConverter 
{ 
    public Visibility TrueValue { get; set; } 
    public Visibility FalseValue { get; set; } 

    public BoolToVisibilityConverter() 
    { 
     // set defaults 
     FalseValue = Visibility.Hidden; 
     TrueValue = Visibility.Visible; 
    } 

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return (bool)value ? TrueValue : FalseValue; 
    } 

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

Następnie w XAML:

<BoolToVisibilityConverter x:Key="BoolToVisibleConverter" 
           FalseValue="Hidden" 
           TrueValue="Visible" /> 
+1

Jeśli możesz użyć XAML 2009, możesz również zrobić to ogólne. Składnia atrybutu: 'Konwerter = {c: BooleanConverter (Widoczność) True = Widoczny, Fałsz = Zwinięty} Składnia elementu:' Jeśli nie możesz użyć XAML 2009, nadal możesz utworzyć ogólną klasę podstawową, ale potrzebujesz klas pochodnych konkretnych dla każdego rodzaju generycznego. –

Powiązane problemy