| 

.NET C# Java Javascript Exception

2
Hallo zusammen,
ich versuche gerade eine ComboBox aus einem MVVM ViewModel zum Leben zu erwecken und stehe dabei etwas auf dem Schlauch.
Als MVVM Framework verwendich noch Caliburn Micro.

Mein ViewModel sieht so aus:
[Export(typeof(IFirmenDaten))]
class FirmenDatenViewModel : Screen,IFirmenDaten
{
DataEntities db;

private firma _CurrentFirma;

public firma CurrentFirma
{
get { return _CurrentFirma; }
set
{
_CurrentFirma = value;
NotifyOfPropertyChange(() => CurrentFirma);
}
}

private ObservableCollection<AuswahlEintraege> _EintraegeStatus;

public ObservableCollection<AuswahlEintraege> EintraegeStatus
{
get { return _EintraegeStatus; }
set
{
_EintraegeStatus = value;
NotifyOfPropertyChange(() => EintraegeStatus);
}
}
//usw.


Der Xaml Teil im View
<ComboBox  ItemsSource="{Binding Path=EintraegeStatus}" Grid.Row="1" Grid.Column="1" x:Name="CurrentFirma"
SelectedValue="{Binding Path=status,Mode=TwoWay}"
SelectedValuePath="Eintrag"
DisplayMemberPath="Eintrag">

Wenn ich wie oben beschrieben verfahre werden zwar die Eintraege aus der Collection EintraegeStatus zu Auswahl angeboten aber nicht der aktuelle Wert in der Property firma.
Offensichtlich wird die Eigenschaft Datacontext von dem Setzen der Eigenschaft Itemssource irgendwie behindert.

Ein explizites Setzen der Datacontext Eigenschaft im CodeBehind mittels
var vModel = (FirmenDatenViewModel)this.DataContext;
this.CurrentFirma.DataContext = vModel.CurrentFirma;

führt dann dazu das zwar der Datacontext stimmt und der Wert status der Property firma angezeigt wird - aber nicht mehr die Auswahl aus EintraegeStatus.

Das erscheint mir auch logisch denn wenn der DataContext der Combobox auf die Property CurrentFirma desetzt wird gibt es hierunter natürlich keine Property EintraegeStatus.

Wenn ich dagegen die Itemssource wie folgt lade:
<ComboBox  ItemsSource="{Binding Source={StaticResource EintraegeLookup}}" Grid.Row="1" Grid.Column="1" x:Name="CurrentFirma"
SelectedValue="{Binding Path=status,Mode=TwoWay}"
SelectedValuePath="Eintrag"
DisplayMemberPath="Eintrag">

Und dann die Statische Resource im Codebehind lade funktioniert es problemlos.
EintraegeLookupViewSource = ((CollectionViewSource)(this.FindResource("EintraegeLookup")));
EintraegeLookupViewSource.Source = new AuswahlEintraegeCollection(db.AuswahlEintraege.Where(i => i.Gruppe == "Status"), db);

Nun möcht ich natürlich eigentlich dieses Laden im Codebehind vermeiden aber ich habe keine Ahnung wie.

Ich hoffe ich habe einigermaßen erklären können was ich meine und bin für jeden Tipp dankbar.

Gruß

asWorks
05.12.2012
asWorks 123 1 5
4 Antworten
1
Ohne die Klasse AuswahlEintraege (und den Rest des ViewModels zu sehen), kann ich Deine Bindings nicht vollständig nachvollziehen.

Evtl. reicht Dir aber auch schon, statt SelectedValue + SelectedValuePath einfach SelectedItem fürs Binding des aktuell ausgewählten Items zu verwenden. Die hierfür korrespondierende ViewModel Property müsste dann vom Typ AuswahlEintraege sein.

UPDATE
Ich habe ein ausführliches, aber auf das Problem reduziertes Codebeispiel für Dich erstellt. Du kannst es schnell nachbilden und schauen, ob das Dein Problem löst.

Die POCOs des Beispiels (Deine EF Model-Klassen)

public class Status
{
public string Text { get; set; }

public static IEnumerable<Status> PossibleStatusValues
{
get
{
for (int i = 0; i < 3; i++)
yield return new Status() { Text = "Status " + i };
}
}

public override string ToString(){ return Text; }
}

public class Firma
{
public Firma()
{
TheStatus = Status.PossibleStatusValues.First();
}

public Status TheStatus { get; set; }
}


Das ViewModel der Firma

public class FirmaViewModel : INotifyPropertyChanged
{
private ObservableCollection<Status> _possibleStatus =
new ObservableCollection<Status>(Status.PossibleStatusValues);

private Firma _model = new Firma();

public ObservableCollection<Status> PossibleStatus
{
get { return _possibleStatus; }
set
{
if (value != _possibleStatus)
{
_possibleStatus = value;
NotifyOfPropertyChanged("PossibleStatus");
}
}
}

public Status CurrentStatus
{
get { return _model.TheStatus; }
set
{
if (value != null && value.Text != _model.TheStatus.Text)
{
_model.TheStatus = value;
NotifyOfPropertyChanged("CurrentStatus");
}
}
}

public event PropertyChangedEventHandler PropertyChanged;

public void NotifyOfPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}


Der relevante Teil der View

<StackPanel>
<TextBlock Text="{Binding CurrentStatus}" />
<ComboBox ItemsSource="{Binding PossibleStatus}"
SelectedItem="{Binding CurrentStatus}" />
</StackPanel>


Bootstrapper

public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);

var view = new MainWindow();
var viewModel = new FirmaViewModel();

view.DataContext = viewModel;
view.Show();
}
}


In diesem Beispiel zeigt mir die Combobox die möglichen Werte für den Status an. Wenn ich einen auswähle, wird dieser Wert als Status der Firma festgelegt. Wenn ich Deine letzten Anmerkungen richtig verstanden habe, ist es das, was Du erreichen möchtest.

HTH
Florian
05.12.2012
ffordermaier 8,4k 3 9
1
Hab auch mal mit Caliburn rumgespielt. Versuch mal folgendes:

ViewModel
...
private AuswahlEintraege _CurrentAuswahl;

public AuswahlEintraege CurrentAuswahl
{
get { return _CurrentAuswahl; }
set
{
_CurrentAuswahl = value;
NotifyOfPropertyChange(() => CurrentAuswahl);
}
}
...


View
...
<ComboBox x:Name="EintraegeStatus" Grid.Row="1" Grid.Column="1"
SelectedItem="{Binding Path=CurrentAuswahl}"
DisplayMemberPath="Eintrag">
</ComboBox>
...

Bei einem DataGrid scheint das zu funktionieren.
05.12.2012
PinBack 687 1 8
Das ist meine Antwort in Form von Code. Gute Ergänzung!
ffordermaier 05.12.2012
0
Hallo Pinback, Hallo ffordermaier,
danke für eure Tipps. Grundsätzlich würde es so funktionieren. Allerdings hätte ich damit das Problem das ich dann den in CurrentAuswahl geschriebenen Wert zurückschreiben müsste nach CurrentFirma was ja der eigentlich Datacontext der ComboBox ist.
Zum besseren Verständnis:
CurrentFirma ist eine Instance einer EntityFramework Klasse firma die eine Property Status hat.
AuswahlEinträge ist eine Collection die letztlich per EntityFramework eine Auswahl von Stati anbietet die dann von der Combobox in das Feld Status eingetragen werden soll.
Ich will die EntityFramework Klassen direkt als Modelle verwenden.

Gruß asWorks
09.12.2012
asWorks 123 1 5
Habe meine Antwort aktualisiert und ein ausführliches Codebeispiel erstellt. Hilft Dir das weiter?
ffordermaier 09.12.2012
0
Hallo Florian,
erstmal vielen Dank für Deine Mühe.
Ja, so funktioniert es.

Gruß

asWorks
PS.
Sorry für die Verspätung - ich war der Meinung ich hätte schon eine Antwort abgeschickt aber irgendwie ist die wohl hier nicht angekommen.
13.12.2012
asWorks 123 1 5
Freut mich, dass ich helfen konnte.
ffordermaier 13.12.2012

Stelle deine .net-Frage jetzt!
TOP TECHNOLOGIES CONSULTING GmbH