ComboBox.SelectedItem TwoWay-Binding to Property



  • Hallo,

    ich habe ein public enum-Property in meiner Klasse, welches ein TwoWay-Binding zu einer ComboBox haben soll.

    Ich bekomme in der ComboBox (siehe Code unten) die richtigen Werte (gemappt durch den Converter) angezeigt. Durch das auswählen eines neuen Wertes in der DropDown-Auswahl, wird jedoch nicht die set-Methode meines Propertys (LeftTable) aufgerufen. Warum? Was mache ich falsch?

    Vielen Dank vorab.

    <!-- DataContext for bindings is specified in code behind {ctor} -->
    <ComboBox Grid.Row="1" Grid.Column="1" Name="comboBoxLeft"
              ItemsSource="{Binding Path=LeftTable, Mode=OneTime, Converter={StaticResource tableEnumTextConverter}}"
              SelectedItem="{Binding Path=LeftTable, Mode=TwoWay}"/>
    


  • Kennt wirklich niemand die Lösung?


  • Administrator

    FrEEzE2046 schrieb:

    Kennt wirklich niemand die Lösung?

    Ich müsste es auch zuerst testen, gerade aber keine Lust Zeit.
    CSL wäre da wahrscheinlich der richtige Mann dafür, bzw. der heisst, glaube ich, jetzt neu David W.

    Was mich persönlich ohne grosse weitere Überlegung etwas stutzig macht, sind zwei Dinge:
    1. Du Bindest ItemSource an LeftTable . Und du bindest SelectedItem an LeftTable . Ist das so wirklich richtig?
    2. Was macht dein Converter da? Der transformiert doch das Objekt, welches an ItemSource gebunden werden soll. Ist das gewollt?

    Grüssli



  • Dravere schrieb:

    1. Du Bindest ItemSource an LeftTable . Und du bindest SelectedItem an LeftTable . Ist das so wirklich richtig?
    2. Was macht dein Converter da? Der transformiert doch das Objekt, welches an ItemSource gebunden werden soll. Ist das gewollt?

    Danke für deine Antwort. Ja, dass ist schon so gewollt. Der Converter konvertiert den Wert meines (enum) Propertys in einen sprechenderen String.
    Das funktioniert auch. Er ist dazu in der Lage sich die Werte abzuholen.



  • Okay, schon klar. Er kann es natürlich nicht zurück konvertieren. Mein Problem ist, dass ich nur sehr ungern strings vergleichen will. Kann man die Konvertierungen auch auf Index-Basis durchführen?

    EDIT:

    public enum MyEnum : int { Val0, Val1, Val2, Val3 }
    
        /* Converts Enum and IEnumerable */
        public class MyEnumConverter : IValueConverter
        {
            Dictionary<string, MyEnum> enumValues = new Dictionary<string, MyEnum>(4);
    
            public MyEnumConverter()
            {
                enumValues.Add("fist val", MyEnum.Val0);
                enumValues.Add("second val", MyEnum.Val1);
                enumValues.Add("third val", MyEnum.Val2);
                enumValues.Add("fourth val", MyEnum.Val3);
            }
    
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return enumValues.Select(s => s.Key);
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return enumValues[(string)value];
            }
        }
    

    Schön find ich anders.



  • Ich hörte meinen Namen? Kann ich stolz drauf sein? 😃

    Du willst also ein Enum an eine ComboBox binden, deine Lösung finde ich schon recht gut und auch legitim.
    Also entweder ein Converter wie du ihn schon hast, oder eine Wrapper Klasse wo du die Enum werte einzeln verpackst.
    Der Converter ist am angenehmsten und durchaus sauber, also ich sehe da nichts schlechtes 🙂
    Über die Performance brauchst du dir keine Gedanken machen, Linq auf ein paar Enum Strings ist lächerlich.

    Was du machen könntest, fals du unbedingt die string vergleiche los werden willst, du bindest nicht SelectedItem sondern SelectedIndex und jagst das durch den Converter 😉

    Was mit noch einfallen würde, du könntest dein Converter "Generischer" machen, dh du übergibst den Enum per ConvertParameter und der Converter baut das dictionary dann direkt auf. So hast du dann ein Converter für alle möglichen Enums.

    Ich kann mir aber auch vorstellen das du bei "Enum an ComboBox" doch so einiges bei Google findest, z.B. bei CodeProject, so etwas hab ich schon oft gehört.



  • @David W

    Danke für deine Antwort. Allgemeni ist kein Problem:

    internal static class EnumHelper
        {
            public static IEnumerable GetValues(Type EnumType)
            {
                if (EnumType.IsEnum)
                    return EnumType.GetFields(BindingFlags.Static | BindingFlags.Public).Select(f => f.GetValue(null));
                else
                    throw new ArgumentException("Type '" + EnumType.Name + "' is not an enum");
    
            }
    
            public static IEnumerable<EnumType> GetValues<EnumType>()
            {
                EnumType e = (EnumType)Enum.ToObject(typeof(EnumType), 0);
                return from f in e.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)
                       select (EnumType)f.GetValue(e);
            }
        }
    
        public class EnumValueConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return EnumHelper.GetValues(value.GetType());
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return value;
            }
        }
    

    Das Problem hier ist aber, dass ich nicht zwingend die enum - Namen direkt dem User anzeigen lasse nmöchte^^, wenn gleich sie dahinter stecken.



  • Leg doch ein dictionary an mit den Text 😃

    public class EnumValueConverter : IValueConverter
    {
        public EnumValueConverter()
        {
            _names = new Dictionary<string, string>();
    
            _names.Add(MyEnum.First.ToString(), "This is the first"); // der enum flag ist der key, kann aus einer resourcedictionary kommen
            _names.Add(MyEnum.Second.ToString(), "This is the second");
        }
    
        private Dictionary<string, string> _names;
    
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Enum.GetNames(typeof(value)).Select(v => _names[v]); // namen anhand der keys selektieren
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return Enum.Parse(typeof(MyEnum), _names.Keys.Where(k => k == value.ToString()).First()); // anhand des namens den enum key zurueck geben
        }
    }
    

    Is jetzt alles natürlich rein Pseudo - kann man bei langerweile noch umbauen. Dein EnumHelper brauchst du auf jeden fall nicht, Enum.GetNames macht das bereits 😃

    Dazu.
    Muss aber sagen das dieser Code gegen Punkt 6. der Lokalisierungsregeln verstößt: Link.
    Wenn man es richtig machen möchte muss man die einzelnen Enums in Objekte verpacken und diese der ComboBox anbieten, ohne Converter.



  • David W schrieb:

    Dein EnumHelper brauchst du auf jeden fall nicht, Enum.GetNames macht das bereits 😃

    Bei mir (SL 4.0) hat die Enum Klasse nur eine Methode "GetName", aber nicht "GetNames"


Anmelden zum Antworten