| 

.NET C# Java Javascript Exception

2
Und zwar so, dass man vom Designer bei der Auswahl unterstützt wird. Sei es der Property-Explorer oder Intellisense im XAML Code. Ab und an passieren mir Tippfehler beim Binding, weil ich mich beim Pfad verschrieben habe, was nicht hätte sein müssen.

Die View kennt jedoch nur DataContext. Ich erinnere mich dunkel an einen zusätzlichen namespace von expression und einem StaticResource, wo das ViewModel drin abgelegt wurde...

Aber dann kennt die View ja wieder das ViewModel...

Wo/Wie setzt ihr denn die ViewModels ? Ich mache das zurzeit im Code:

view.DataContext = viewModel;

Vielen Dank für die Lösung!
News:
16.02.2011
Florian Mätschke 370 1 7
5 Antworten
2
Meinst du:

<Window class="MyWindow"
...
xmlns:my="clr-namespace:MyNamespace.Interfaces;assembly=MyNamespaeDll"
>

<my:VM x:Key="MyVM" />

<ControlXX
ItemsSource="{Binding Source={StaticResource MyVM},
Path=MySampleCollectionProp}" />

// @edit: vergessen: Zugriff vom Code behind - für Befüllung 
private VM GetVMResource
{
return (VM) FindResource("MyVM");
}



// z. B.:
VM myVM = GetVMResource();
myVM.Fill();


Grüße
maria
16.02.2011
Maria Simlinger 1,1k 1 9
1
also in Silverlight setzte ich das ViewModel im CodeBehind so:

[Import(ViewModelTypes.ProduktPickerViewModel)]
public object ViewModel
{
set
{
DataContext = value;
}
}

dazu nutze ich MEF und exportiere das ViewModel so
[Export(ViewModelTypes.ProduktPickerViewModel)]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ProduktPickerViewModel : ViewModelBase


Im CodeBehin der View muss dann noch
CompositionInitializer.SatisfyImports(this);
ausgeführt werden.

ViewModelTypes ist nur eine Datei die solche Einträge enthält
public const string ProduktPickerViewModel = "ProduktPickerViewModel";

um Magic Strings zu vermeiden.

Im Grunde nicht viel Aufwand umd lose Kopplung mit MEF zu erreichen und das ViewModel zur Laufzeit zu binden.

mfg
Wend0rlin
24.02.2011
Wend0rlin 46 2
DANKE, das probiere ich mal!
Florian Mätschke 24.02.2011
0
Wird so jedesmal eine Instanz des ViewModels von der View erzeugt? - Ich vermute mal ja.

Mit GetVMResource() holt man sich dann diese Instanz und ruft auf dieser den Befehl Fill() von außen auf, damit die Daten geladen werden. - Ich vermute mal das Fill() alleine nur als Beispiel dient, und man eigentlich der Methode noch Parameter übergibt, welche Daten es nutzen soll.

Jetzt stellt sich mir noch die Frage: Wieso kennt jetzt die View in XAML das ViewModel ?

Danke für die Antwort!
17.02.2011
Florian Mätschke 370 1 7
Natürlich sollte der Aufruf von Fill() gecached werden, falls nötig.

GetVMResource holt sich die Resource aus XAML = Instanziertes Objekt.

Mit dem Einbinden des VM-Namespaces kannst du das VM in XAML verwenden, Path wird wie bei allen anderen Klassen auch immer zur Laufzeit ausgewertet. Falls du dafür eine Lösung gesucht hast wäre mir keine bekannt, aber das liegt wie gesagt nicht daran, dass VM eine selbst erstellte Klasse ist, sondern works as designed.
Maria Simlinger 17.02.2011
0
Genau, so wird jedesmal eine Instanz des ViewModels erzeugt.
Im Prinzip mache ich das so:

public partial class ContactWindow : UserControl, IContactView
{
public void BindToViewModel(ContactWindowViewModel viewModel)
{
_viewModel = viewModel;
DataContext = viewModel;
}
}

public class ContactWindowViewModel: INotifyPropertyChanged
{
public ContactWindowViewModel(IContactView view, IMainViewModel mainViewModel)
{
_view = view;
_mainViewModel = mainViewModel;

_view.BindToViewModel(this);
}
}


Es ist aber nicht verboten, wenn die View das ViewModel kennt. Vor allem kannst du es nutzen, wenn du das ViewModel als Beispieldatenquelle in der View nutzt:
<Grid x:Name="LayoutRoot" d:DataContext="{d:DesignData /SampleData/ContactSampleData.xaml}"/>


Und bei den Beispieldaten füllst du das ViewModel mit Beispieldaten:
<SilverWave_Core_ViewModel:ContactWindowViewModel xmlns:SilverWave_Core_ViewModel="clr-namespace:SilverWave.Core.ViewModel;assembly=SilverWave.Core" Email="Nam aliquam class aenean curae" IsValid="True" Message="Sed integer cras maecenas mauris" Name="Dis duis quisque"/>
17.02.2011
Andy Stumpp 509 1 6
0
Wegen Intellisense:
Das kann nur funktionieren, wenn VS von vorneherein weiss, welchen Typ dein DataContext haben wird, da der Typ aber auf Object festgelegt ist geht das über den Weg zur DesignZeit nicht (evtl gibt es irgendein Über-Tool, das analysiert was du dem DataContext zuweißt - das wird aber aufwändig, weil auch für alle UnterElemente festgehalten werden muss welchen Typ der DataContext hat, um da das richtige Intellisense anbieten zu können). Umgehen könnte man das nur, indem man jeder View eine Typed ViewModel DependencyProperty spendiert - man also zumindest auf höchster Ebene den DataContext umschifft.
Dann wird das Binden aber ziemlich kompliziert, weil du dich immer auf dieses Property der View beziehen musst und wenn du von einem untergeordneten Element auf das Property zugreifen willst musst du dich erstmal auf dein RootElement beziehen und von dem das Property abrufen...
Also etwa so:
public partial class Control
{
#region dependency properties

private static readonly DependencyProperty ModelProperty = DependencyProperty.Register(
"Model",
typeof(Model),
typeof(Control),
new PropertyMetadata(OnModelChanged));

private static void OnModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
}

#endregion

#region properties

public Model Model
{
get { return (Model)GetValue(ModelProperty); }
set { SetValue(ModelProperty, value); }
}
#endregion

public Control()
{
InitializeComponent();
}
}

XAML:
<myXmlns:Control
Name="root"
x:Class="Tis.Modules.AffiliateManagement.Affiliate.View"
xmlns:myXmlns="clr-namespace:...">
...
<TextBox Text={Binding ElementName=root, Path=Model.MyPath}/>

...
</myXmlns:Control>


Für meinen Geschmack das bisl Intellisense nicht wert.
Wenn man sich bei der althergebrachten DataContext-Methode verschreibt muss man halt sein Binding debuggen mit PresentationTraceSources.TraceLevel=High, das geht recht schnell.

Ansonsten würde ich auch den MEF oder MefedMVVM-Ansatz von Wend0rlin als "The way to go" bezeichnen.

Edit:
Das Model kann man dann in Xaml (wie oben schonmal beschrieben setzen bzw. statt es in Xaml zu erzeugen dann einfach von irgendwoher binden) oder auch im Code setzen.
01.06.2011
Sparky 109 3

Stelle deine Mvvm-Frage jetzt!