none
Converter mit zweit Parametern verwenden RRS feed

  • Frage

  • Hallo,

    ich möchte einen Converter erstellen welcher eine Zahl in einer TextBox mit dem Wert factor multipliziert bzw dividiert bei der Rückgabe.
    Für den Fall, dass factor statisch ist habe ich eine Lösung:

    public class UnitConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return (double)value * 10;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            value = Regex.Match(value.ToString(), @"\d+").Value;
            double dVal = System.Convert.ToDouble(value);
            return (dVal / 10);
        }
    }

    In diesem Fall ist factor = 10. 
    Nun möchte ich aber factor variable halten und diesen Wert ebenso wie die eigentliche Zahl an die TextBox binden.

    <TextBox Name="txb" Text="{Binding MyValue, Converter={StaticResource UnitConverter}, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" Width="200" />

    Ich bin auf der Suche nach einer Lösung auf den IMultiValueConverter gestossen.
    Ist dieser eine gute Lösung für das Problem?
    Ich habe es damit versucht, aber die ConvertBack-Methode umfasst nur ein value, im Gegensatz zur Convert-Methode mit object[] value. Da weiß ich nicht, wie ich den Wert erhalte.

    Wie kann ich den Faktor (10) durch eine Variable ersetzen?

    Grüße,
    Frank


    www.energiewende-mach-ich-selbst.de

    Montag, 9. November 2015 16:36

Antworten

  • Hi Frank,
    in Deiner Variante des MultiValueConverter gibst Du das Ergebnis nicht im geforderten Typ zurück, d.h., die gebundene Text-Eigenschaft ist vom Typ String und der berechnete Wert vom Typ double. Option Strict Off wie in VB.NET gibt es in C#.NET nicht. Konvertiere das Ergebnis (result) in eine Zeichenkette und das Programm funktioniert.

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    • Als Antwort markiert frank me Dienstag, 10. November 2015 08:50
    Dienstag, 10. November 2015 08:32

Alle Antworten

  • Hallo Frank,

    sofern der Faktor zumindest im XAML statisch festgelegt werden kann, kannst du die ConvertParameter-Eigenschaft im Binding festlegen. Diesen erhältst du anschließend in den Convert/ConvertBack-Methoden über den paramater-Parameter.

    Möchtest du den Faktor aber auch binden, so solltest du zu einem Multi-Konverter greifen. Bei diesem erhältst du in der Convert-Methode ein Array von Werten welche du im XAML durch Bindungen festlegen kannst. Die ConvertBack-Methode muss es wieder schaffen aus dem einen Zielwert alle Ausgangswerte wiederherzustellen, daher die anderen Parameter.

    Um einen Wert konstant zu binden und damit von A in B und wieder zurück zu rechnen ist soweit ich weiß dann nur über eine eigene Implementierung eines Bindings möglich. Dies kann durch das Erben von Binding oder BindingBase geschehen, wobei hier dann eine extra Abhängigkeitseigenschaft für den Faktor deklariert werden muss.


    Tom Lambert - .NET (C#) MVP
    Wozu Antworten markieren und für Beiträge abstimmen? Klicke hier.
    Nützliche Links: .NET Quellcode | C# ↔ VB.NET Konverter | Account bestätigen (Verify Your Account)
    Ich: Webseite | Code Beispiele | Facebook | Twitter | Snippets

    Montag, 9. November 2015 18:53
    Moderator
  • Hi Frank,
    der Converter könnte so aussehen:

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
          double wert = 0;
          if (value != null) double.TryParse(value.ToString(), out wert);
          double par = 1;
          if (parameter != null) double.TryParse(parameter.ToString(), out par);
          return wert * par;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
          double wert = 0;
          if (value != null) double.TryParse(value.ToString(), out wert);
          double par = 1;
          if (parameter != null) double.TryParse(parameter.ToString(), out par);
          return wert/par;
        }

    Und dazu der XAML:

        <TextBox Text="{Binding MyValue, 
    Converter={StaticResource conv}, 
    ConverterParameter=10, 
    UpdateSourceTrigger=PropertyChanged, 
    Mode=TwoWay}" 
    Margin="10" />
    


    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    Montag, 9. November 2015 18:58
  • Hallo und danke für die Antworten,

    @Peter: der Faktor soll aus dem Codebehind kommen und variabel sein und von daher funktioniert die statische Zuweisung nicht. (das Objekt parameter zu nutzen finde ich trotz dem gut zu wissen)

    @Tom:

    ich habe noch eine Variante gefunden die mir vielversprechend aussieht.
    Mit dem IMultiValueConverter kann ich den Faktor als Converter-interne Variable speichern.
    Wenn ich in die TextBox einen Wert eintrage so wird dieser richtig an die Eigenschaft im Codebehind weitergegeben (durch Faktor dividiert).
    Wenn ich aber den Wert im codebehind ändere (Buttonklick), so wird dieser nicht in der TextBox dargestellt, trotz dass in der Methode ConvertBack der richtige Wert zurückgegeben wird.

    Warum wird Factor.Converter.result nicht dargestellt?

    Hier mein Code zum testen:

    <Window x:Class="ConverterTest01.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:my="clr-namespace:ConverterTest01"
            Title="Converter Test 01" Height="170" Width="230">
        <Window.Resources>
            <ResourceDictionary>
                <BooleanToVisibilityConverter x:Key="BoolToVis" />
                <my:FactorConverter x:Key="FactorConverter" />
            </ResourceDictionary>
        </Window.Resources>
        <StackPanel Margin="0 10 0 0">
            <TextBox Name="txb" Width="200" Background="LightYellow">
                <TextBox.Text>
                    <MultiBinding Converter="{StaticResource FactorConverter}" UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" >
                        <Binding Path="MyValue" />
                        <Binding Path="Factor" />
                    </MultiBinding>
                </TextBox.Text>
            </TextBox>
            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0 10">
                <Button Content="-1" Name="btnDown" Click="btnUp_Click" Padding="10" />
                <Button Content="+1" Name="btnUp" Click="btnUp_Click" Padding="10" Margin="10 0 0 0"  />
            </StackPanel>
            <Label Name="lblInfo" HorizontalAlignment="Center" />
        </StackPanel>
    </Window>

    codebehind + converter:

    namespace ConverterTest01
    {
        public partial class MainWindow : Window, INotifyPropertyChanged
        {
            private double myValue;
            public double MyValue
            {
                get { return myValue; }
                set
                {
                    myValue = value;
                    NotifyPropertyChanged();
                    if (lblInfo != null)
                        lblInfo.Content = myValue.ToString();
                }
            }
            private int factor;
            public int Factor
            {
                get { return factor; }
                set
                {
                    factor = value;
                    NotifyPropertyChanged();
                }
            }
    
            public MainWindow()
            {
                DataContext = this;
                MyValue = 66;
                Factor = 10;
                InitializeComponent();
            }
    
            private void btnUp_Click(object sender, RoutedEventArgs e)
            {
                Button btn = (Button)sender;
                if (btn == btnUp)
                    MyValue++;
                else if (btn == btnDown)
                    MyValue--;
            }
    
            #region PROPERTY CHANGED
            public event PropertyChangedEventHandler PropertyChanged;
            private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
            {
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
            #endregion
        }
    
        public class FactorConverter : IMultiValueConverter
        {
            double factor;
    
            object IMultiValueConverter.Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
            {
                double myValue = System.Convert.ToDouble(values[0]);
                factor = System.Convert.ToDouble(values[1]);
                double result = myValue * factor;
                return result;
            }
    
            object[] IMultiValueConverter.ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
            {
                string myValue = Regex.Match(value.ToString(), @"\d+").Value;
                if (myValue.Length > 0)
                {
                    double dVal = System.Convert.ToDouble(myValue);
                    double dResult = dVal / factor;
                    object[] result = new object[] { dResult };
                    return result;
                }
                else
                    return new object[] { 0 };
            }
        }
    }
    Grüße,
    Frank

    www.energiewende-mach-ich-selbst.de

    Dienstag, 10. November 2015 07:41
  • Hi Frank,
    in Deiner Variante des MultiValueConverter gibst Du das Ergebnis nicht im geforderten Typ zurück, d.h., die gebundene Text-Eigenschaft ist vom Typ String und der berechnete Wert vom Typ double. Option Strict Off wie in VB.NET gibt es in C#.NET nicht. Konvertiere das Ergebnis (result) in eine Zeichenkette und das Programm funktioniert.

    --
    Viele Grüsse
    Peter Fleischer (MVP, Partner)
    Meine Homepage mit Tipps und Tricks
    Kommas richtig setzen!
    Schüler sagen, Lehrer haben es gut.
    Schüler, sagen Lehrer, haben es gut

    • Als Antwort markiert frank me Dienstag, 10. November 2015 08:50
    Dienstag, 10. November 2015 08:32