Autor Beitrag
FrEEzE2046
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
BeitragVerfasst: Di 11.05.10 11:50 
Hallo,

ich möchte ein Enum an eine ComboBox binden. Dafür habe ich mir folgende Klassen erstellt:

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
internal static class EnumHelper<EnumType> where EnumType : struct
{
    public static IEnumerable<EnumType> GetEnumValues()
    {
        EnumType e = (EnumType)Enum.ToObject(typeof(EnumType), 0);
        return from f in e.GetType().GetFields(BindingFlags.Static | BindingFlags.Public)
                select (EnumType)f.GetValue(e);
    }
}

/* Converts Enum and IEnumerable */
public class EnumValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException(); 
    }

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


Nun funktioniert EnumHelper<MeinEnum>.GetEnumValues() ganz wunderbar und ich kann auch in der ComboBox die EnumElemente sehen. Nur möchte ich wie gesagt ein Binding haben. Durch den Converter müsste mir das eigentlich gelingen. Ich frage mich jedoch, wie ich meine TemplateKlasse EnumHelper innerhalb von EnumValueConverter.Convert aufrufen kann, da der Typ ja hier durch die Klasse Type übergeben wird.

Ja, ich könnte EnumHelper als nicht generische Klasse deklarieren, aber ich ziehe Fehler zur Kompilierzeit denen zur Laufzeit vor.


Zuletzt bearbeitet von FrEEzE2046 am Di 11.05.10 12:13, insgesamt 1-mal bearbeitet
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 11.05.10 12:10 
Enum.GetValues ;) .

Wenn du außerhalb des Value-Converters doch lieber Typsicherheit haben willst, genügt ja schon ein kleiner Wrapper:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
public static IEnumerable<T> GetValues()
  where T : struct
{
  return Enum.GetValues(typeof(T)).Cast<T>();
}

_________________
>λ=
FrEEzE2046 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
BeitragVerfasst: Di 11.05.10 12:12 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Enum.GetValues ;) .

Wenn du außerhalb des Value-Converters doch lieber Typsicherheit haben willst, genügt ja schon ein kleiner Wrapper:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
public static IEnumerable<T> GetValues()
  where T : struct
{
  return Enum.GetValues(typeof(T)).Cast<T>();
}


Würde ich wohl genau so machen, nur gibt es in Silverlight kein GetValues, was ich wohl mal hätte erwähnen sollen ;-)
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 11.05.10 12:15 
Ah, Silverlight, schade ;) .
Das Prinzip bleibt trotzdem das gleiche: Baue zuerst eine untypisierte Methode und darüber dann einen typisierten Wrapper.

_________________
>λ=
FrEEzE2046 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
BeitragVerfasst: Di 11.05.10 12:17 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Ah, Silverlight, schade ;) .
Das Prinzip bleibt trotzdem das gleiche: Baue zuerst eine untypisierte Methode und darüber dann einen typisierten Wrapper.


Verständnisproblem: Ich muss die Methode aber doch im Converter aufrufen und der hat nur einen untypisierten Parameter, den ich dann nicht an eine typisierte Methode übergeben kann.

Du siehst ja anhand meines Codes was ich meine. Wie willst du das machen?
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 11.05.10 12:41 
Deshalb
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Wenn du außerhalb des Value-Converters doch lieber Typsicherheit haben willst

:)
Im Value-Converter brauchst du die untypisierte Methode, das ist schon richtig.

ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
  static class EnumHelper
  {
    public static IEnumerable GetValues(Type enumType)
    {
      return enumType.GetFields(BindingFlags.Static | BindingFlags.Public).Select(f => f.GetValue(null));
    }

    public static IEnumerable<T> GetValues<T>()
      where T : struct
    {
      return GetValues(typeof(T)).Cast<T>();
    }
  }

_________________
>λ=
FrEEzE2046 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
BeitragVerfasst: Di 11.05.10 12:46 
Also muss ich die untypisierte GetValue() Variante im Converter verwenden.

Das hier:
ausblenden C#-Quelltext
1:
f => f.GetValue(null)					


kapier ich allein syntaktisch überhaupt nicht. Hast du eine Erklärung dazu?
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 11.05.10 12:55 
user profile iconFrEEzE2046 hat folgendes geschrieben Zum zitierten Posting springen:
Hast du eine Erklärung dazu?
Das ist ein Lambda-Ausdruck, die Grundlage von LINQ. Die Syntax ist meine eigene Vorliebe und semantisch äquivalent zu deinem from-select; ich wollte einfach mal testen, ob dir das bewusst ist *g* .

_________________
>λ=
FrEEzE2046 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
BeitragVerfasst: Di 11.05.10 13:14 
Okay,

ist also eine Lambda-Funktion dessen Rückgabemenge selektiert wird. Okay, soweit klar.
Leider bekomme ich das ganze immer noch nicht zum laufen:

ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
// EnumHelper.cs

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);
        // or: return GetValues(typeof(EnumType)).Cast<EnumType>();
    }
}


/* Converts Enum and IEnumerable */
public class EnumValueConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return EnumHelper.GetValues(targetType);
    }

  public object ConvertBack (object value, Type targetType, object parameter, CultureInfo culture)
  {
        return value;
  }
}


ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
// Survey.xaml.cs

public partial class Survey : UserControl
{
    public enum SurveyCategory
    {
        test1,
        test2,
        test3,
        test4
    }

    public SurveyCategory Category { get; set; }
}


ausblenden XML-Daten
1:
2:
3:
4:
5:
6:
7:
8:
9:
<UserControl x:Class="WebSite.Views.Survey">
    <UserControl.Resources>
        <local:EnumValueConverter x:Name="EnumConverter"/>
    </UserControl.Resources>

    <ComboBox x:Name="cbCategory"
        ItemsSource="{Binding Path=Category, Mode=OneTime, Converter={StaticResource EnumConverter}}"
        SelectedItem="{Binding Path=Category, Mode=TwoWay}" />
</UserControl>



Leider ist der Inhalt der ComboBox weiterhin leer. Was mache ich falsch?
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 11.05.10 13:41 
Habe es mal unter WPF getestet, die könnten langsam ruhig mal mit der Final der SL4-Tools rausrücken...
Dem Converter habe ich statt x:Name ein x:Key verpasst und im Konstruktor DataContext = this; gesetzt. Wenn das Data Binding dann irgendwann mal anspringt, solltest du wie ich eine ArgumentException bekommen, denn im Converter muss es EnumHelper.GetValues(value.GetType()) heißen. Danach sah es ganz gut aus :zustimm: .

_________________
>λ=
FrEEzE2046 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
BeitragVerfasst: Di 11.05.10 14:28 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
im Konstruktor DataContext = this; gesetzt.


Im Konstruktor von EnumValueConverter oder welchen meinst du?
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 11.05.10 14:47 
Im Konstruktor des UserControls, irgendwo muss das Binding seine Daten herbekommen.

_________________
>λ=
FrEEzE2046 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 109

Windows 98, 2000, XP Pro, Vista Ultimate 32 & 64 Bit, Windows 7 Beta 64 Bit
C/C++, C# (VS 2008 TeamSystem) - Delphi (Delphi 5) - Java (Eclipse)
BeitragVerfasst: Di 11.05.10 15:16 
user profile iconKha hat folgendes geschrieben Zum zitierten Posting springen:
Im Konstruktor des UserControls, irgendwo muss das Binding seine Daten herbekommen.


Ja, hat sich schon geklärt. Trotzdem danke!