Laden...

[erledigt] DataTable - ComboBox - Enum

Erstellt von KST vor 11 Jahren Letzter Beitrag vor 11 Jahren 3.936 Views
K
KST Themenstarter:in
44 Beiträge seit 2012
vor 11 Jahren
[erledigt] DataTable - ComboBox - Enum

Bitte kurze Hilfe, bevor ich mich vor einen Langläufer werfe:

  • DataTable Inhalt wird mittels einer ComboBox und Textboxen dargestellt

  • Inhalt besteht aus PErsonendaten, darunter auch eine Anrede

  • Anreden sind als Enum definiert

  • Inhalt der ComboBox ist an die Enum Werte von Anrede gebunden

Wird eine Zeile im DataTable selektiert, möchte ich, dass abhängig vom Inhalt in der AnredeZelle, der richtige Eintrag in der ComboBox selektiert ist und bei Änderung in der ComboBox, soll diese auch in den DataTable übernommen werden:

Funktiniert mit einer TExtbox in Verbinung mit einer ComboBox und Enums wunderbar ohne Converter in beide Richtungen. Hier schaffe ich es nur Änderungen in Richtung ComboBox DataTable durchzuführen.

ComboBox:


 <ComboBox Height="24" HorizontalAlignment="Left" Margin="69,10,0,0" 
                  Name="neuAnrede_comboBox" VerticalAlignment="Top"
                  Width="76" IsTabStop="True" TabIndex="1"
                  ItemsSource="{Binding Source={StaticResource AnredenValues}}">
           
        <ComboBox.SelectedItem>
             <Binding Path="Anrede"
                 UpdateSourceTrigger="PropertyChanged"
                 Mode="TwoWay">
             </Binding>
        </ComboBox.SelectedItem>
</ComboBox>

Wie bekomme ich den Wert der Zelle und nicht das ganze RowItem und warum gehts in die eine Richtung problemlos und in die andere nicht?

Danke für Hilfe

1.378 Beiträge seit 2006
vor 11 Jahren

Wie wird ein Eintrag im Datatable selektiert? Listbox?

Was ist die DataSource "Grundlage" deiner ComboBox und Textboxen? Eine DataRow? Ein DataTable?

Was für einen Datentyp hast du denn im DataTable für die Spalte Anrede? Int, String oder explizit deinen Enum-Typ?

Was genau passiert denn(nicht) in der ComboBox? Wie hast du getestet, dass der Wert der ComboBox in das DataTable geschrieben wird und wie verhält es sich denn beim Laden der Werte?

Und für XML Code gibt es bessere Formatierungsmöglichkeiten hier.

Lg, XXX

K
KST Themenstarter:in
44 Beiträge seit 2012
vor 11 Jahren

Hi!

-Personendaten kommen aus eine MS SQL DB
-Anrede in der DB mittels Check Constraint auf "Herr" bzw "Frau" "Fräulein" etc. abgesichert
-Gespeichert werden Strings

-Laden der DAten geschieht mittels SqlDataAdapter, dieser befüllt eine DataSet, von dort hol ich mir die benötigten Daten und stelle sie einem DataGrid als DataView zur Verügung, da ich die Filtermöglichkeiten der DView nutze.

  • Wenn ich Daten editieren möchte, betrifft es die im Moment selektierte Row der der DataVew (Selektion erfolgt im DataGrid). Die ComboBox soll also nur dazu dienen, die mögliche Auswahl genau auf "Herr" Frau", "Fräulein" einzuschränken. Dies erreiche ich dadurch, dass ich alle zulässigen Anreden als Enum Verwalte (=Grundlage für die ComboBox Einträge)

  • Wenn ich nun eine Zeile editieren möchte, ist in der Combobox nichts selektiert, obwohl der Eintrag in der DataView z.B. "Herr" ist. (Stimmt nicht ganz: Es ist das RowView Obkekt, dass in der ComboBox nicht dargstellt wird) Ändere ich nun in der ComboBox auf Frau (Einträge lt Enum alle vorhanden), ändert sich auch die Zelle in der DView und dies ohne Converter. Ändere ich direkt im Datagrid, ändert sich aber der Eintrag in der ComboBox nicht!

D.h.:
ComboBox Änderung in Richtung DataView --> ok
Änderungeg/Darstellung der DataView Inhalte in Richtung comboBox --> Darstellung nicht ok (da mahc ich was falsch)

1.378 Beiträge seit 2006
vor 11 Jahren

Und die ItemsSource der ComboBox ist eine DeinEnum[], String[]?

SelectedItem funktioniert nur, wenn quell und zieltyp identisch sind - du ladest gerade strings aus der Datenbank und hast aber EnumWerte(welche keine Strings sind) in deiner ComboBox. Ändere mal deine ItemsSource auf string[] dann sollte es denke ich hinhauen.

Lg, XXX

K
KST Themenstarter:in
44 Beiträge seit 2012
vor 11 Jahren

Die ItemsSource ist ein String[], bereitgestellt im Rahmen eines DataProviders, der alle vorhanden Einträge der Anrede ausliest:


<ObjectDataProvider MethodName="GetValues"
                        ObjectType="{x:Type sys:Enum}"
                        x:Key="AnredenValues">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:Anreden" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>

Die Werte bekomm ich dann auch als String ins ComboBox Item.

Ich denke, das Problem ist, dass ich bei der Auswahl einer DataGrid Zeile eine RowView bekomme, nur weiss ich nicht, wie ich innerhalb dieser auf die Zelle "Anrede" als String zugreifen kann.

Ich habe die Enums: None, Frau, Herr,...

Wäre nichts ausgewählt, würde none aufscheinen.

Ich frage deshalb, weil genau dieser Weg im Rahmen von TextBox problemlos in beide Richtungen funktioniert und sämliche Konvertierungen c# automatisch übernimmt.

1.378 Beiträge seit 2006
vor 11 Jahren

//Edit: Schwachsinn gepostet...

trotzdem: GetValues gibt keine Strings zurück sondern wie der Name schon sagt die Werte - Verwende stattdessen GetNames im DataProvider.

K
KST Themenstarter:in
44 Beiträge seit 2012
vor 11 Jahren

Bsp.: Viielleicht drück ich mich schlecht aus:

Stellvertretend für den DataTable die Klasse Person:


public class Person : INotifyPropertyChanged
    {

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, e);
        }

        Anreden anr;
        
        public Anreden Anr
        {
            get { return anr; }
            set 
            {
                anr = value;
                OnPropertyChanged(new PropertyChangedEventArgs("Anr"));
            }
        }

    }


Mein Enum:


public enum Anreden
    {
        None, Herr, Frau,
    }

Main:


<Window x:Class="WpfApplication10.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication10"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ComboBox Height="72" HorizontalAlignment="Left" Margin="154,118,0,0"
                  Name="comboBox1" VerticalAlignment="Top" Width="213">
            <ComboBox.SelectedItem>
                <Binding Path="Anr"
                         UpdateSourceTrigger="PropertyChanged"
                         Mode="TwoWay">                                  
                </Binding>
            </ComboBox.SelectedItem>
        </ComboBox>
        <TextBox Height="50" HorizontalAlignment="Left"
                 Margin="166,245,0,0" Name="textBox1" 
                 VerticalAlignment="Top" Width="201" >
            <TextBox.Text>
                <Binding Path="Anr"
                         UpdateSourceTrigger="PropertyChanged"
                         Mode="TwoWay">
                </Binding>
            </TextBox.Text>
            
        </TextBox>
    </Grid>
</Window>


Code:



public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Person p;
            p = new Person();

            comboBox1.ItemsSource = Enum.GetValues(typeof(Anreden));
            comboBox1.DataContext = p;          

            textBox1.DataContext = p;
            

        }
    }


Das geht in beide Richtungen, konvertiert automatisch und validiert!
TextBox lässt keine anderen Einträge als die vorhanden Anreden zu!

Das wäre schon praktisch!

1.378 Beiträge seit 2006
vor 11 Jahren

Aber ließ und versteh doch was ich sagen will: SelectedItem kann nicht automatisch irgendwelche Zurodnungen treffen, wenn die Quell- und Ziel- Typen unterschiedlich sind.

Einen Vorschlag hab ich bereits gemacht indem du die Enumwerte auf Strings änderst.

Alternativ kannst du das DataTable typisieren und änderst die Spalte Anrede auf den Typ "Anrede" oder du baust im SelectedItem Binding einen Converter ein, welcher von String auf dein Enum und Retour konvertiert.

Das WPF so gscheit ist und von SelectedItem(Enum)->DataRow(String) zu konvertieren kann man annehmen nachdem jedes Objekt eine Methode .ToString() besitzt aber wie soll .NET im Umkehrschluß wissen, dass dein String im DataTable ein Anrede Typ ist???

Also die zwei(drei) Möglichkeiten hast du.

Lg, XXX

K
KST Themenstarter:in
44 Beiträge seit 2012
vor 11 Jahren

Hätte ich jetzt mal angenommen wenn es um Strings geht, da .Net bei TextBox.Text auch so gescheit ist, den String (ohne Converter) nach Enum umzuwandeln!

1.378 Beiträge seit 2006
vor 11 Jahren

Du vermischt einfach Äpfel und Birnen - Bei einer TextBox gibt es keine Items zu selektieren.

K
KST Themenstarter:in
44 Beiträge seit 2012
vor 11 Jahren

Schau, ich wollte nur demonstrieren was ich meine und mir gegebenenfalls eine Converter sparen:

In der TextBox wähle ich nichts aus:

Wenn du kurz das Bsp anschaust:

-Die comboBox lässt mich zwischen None, Herr, Frau auswählen. Die Auswahl wird in die TextBox als String übernommen.

-Im Umkehrschluss: Ich gebe manull in der TextBox Herr (als String) ein, und dieser wird ohne Converter in einen Enum vom Typ Anreden umgewandelt.

Nix für Ungut, daher war ich der Meinung, wenn ich auf den String der Zelle der ausgewählten Row komme, wird das wohl auch funktionieren!

Und danke dennoch für die Vorschläge!! 😃

K
KST Themenstarter:in
44 Beiträge seit 2012
vor 11 Jahren

Hi!

Der Ordnung halber:

2 Lauffähige Varianten:

  1. Wie xxxprod geschrieben und ich zu spät gesehen: mit GetNames anstatt GetValues im ObjectDataProvider funktioniert es in beide Richtungen ohne Converter.

<ObjectDataProvider MethodName="GetNames"
                            ObjectType="{x:Type sys:Enum}"
                            x:Key="AnredenValues">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:Anreden" />
            </ObjectDataProvider.MethodParameters>
</ObjectDataProvider>

Binding:


<ComboBox Height="24" HorizontalAlignment="Left" Margin="69,10,0,0" 
                  Name="neuAnrede_comboBox" VerticalAlignment="Top"
                  Width="76" IsTabStop="True" TabIndex="1"  IsSynchronizedWithCurrentItem="True"
                  ItemsSource="{Binding Source={StaticResource AnredenValues}}">
            <ComboBox.SelectedValue>
                <Binding Path="Anrede"
                         Mode ="TwoWay"
                         UpdateSourceTrigger="PropertyChanged">
                </Binding>
            </ComboBox.SelectedValue>       
</ComboBox>

  1. Man schreibt einen Converter

class ConverterComboToEnum : IValueConverter
    {
        public object ConvertBack(object value, Type targetType,
            object parameter, CultureInfo culture)
        {
            String val;
            val = value.ToString();

            if (String.IsNullOrEmpty(val))
            {
                return DependencyProperty.UnsetValue;
            }
            return val;
        }

        public object Convert(object value, Type targetType,
            object parameter, CultureInfo culture)
        {
            String val;
            val = value.ToString();

            if (String.IsNullOrEmpty(val))
            {
                return DependencyProperty.UnsetValue;
            }
            return (Anreden)Enum.Parse(typeof(Anreden), val);
        }

    }

Und bindet ihn dann im XAML ein:


<Window.Resources>
        
        <local:ConverterStringToBool x:Key="stbconverter" />
        <local:ConverterComboToEnum x:Key="cteconverter"/>

        <ObjectDataProvider MethodName="GetValues"
                            ObjectType="{x:Type sys:Enum}"
                            x:Key="AnredenValues">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:Anreden" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
        
</Window.Resources>
.
.
.

 <ComboBox Height="24" HorizontalAlignment="Left" Margin="69,10,0,0" 
                  Name="neuAnrede_comboBox" VerticalAlignment="Top"
                  Width="76" IsTabStop="True" TabIndex="1"  IsSynchronizedWithCurrentItem="True"
                  ItemsSource="{Binding Source={StaticResource AnredenValues}}">
            <ComboBox.SelectedValue>
                <Binding Path="Anrede"
                         Mode ="TwoWay"
                         UpdateSourceTrigger="PropertyChanged"
                         Converter="{StaticResource cteconverter}">
                </Binding>
            </ComboBox.SelectedValue>       
</ComboBox>

LG & Danke

Hinweis von winSharp93 vor 11 Jahren

Bitte C#-Code in CSHARP-Tags und XAML Code in XML-Tags!!!