Validation in einem Datagrid / Datacontext unter WPF

  • WPF

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Validation in einem Datagrid / Datacontext unter WPF

    Ich stell mich ma wieder zu blöd an X(
    ich hab ein Datacontext mit einer Tabelle "Anreden". Da die natürlich unique sein sollen, sind die auch gleich als Primärschlüsselspalte angelegt. Ich habe dann die Tabelle an ein Datagrid gebunden.
    Bei Eingabe identischer anreden und dem Versuch das zu speichern, knallt es richtigerweise beim context.SubmitChanges(). Nun ist es natürlich viel schöner, wenn der Tastendrücker am Verlassen des Datagrid gehindert würde, wenn er sowas versucht einzugeben. Also hab ich mittels ValidatesOnExceptions=True die Validierung aktiviert und eine Klasse ValidationRule dafür gedichtet. Es wird dabei die Tabelle durchlaufen und nach identischen Einträgen durchsucht. Das funktioniert soweit für die Einträge, die bereits gespeichert wurden. Trage ich aber ohne zwischenzeitliches Speichern mehrmals das Gleiche ein, wird zwar die Rule ausgeführt, aber diese Einträge stehen natürlich noch nicht in der Tabelle.
    Davon abgesehen halte ich es für doof, in der Visualisierung doch wieder an den Daten rumzudocktern.
    Der Versuch, eine eigene Exception im datacontext beim "AnredenChanging" auszulösen geht zwar, löst aber keine Validierung im Datagrid aus. Da wirds dann wieder sone doofe Messagebox.

    Es liefe also darauf hinaus, sich die CollectionView in der Rule-Klasse zu besorgen um deren Liste zu durchlaufen!? Oder was gibs da noch für eine Möglichkeit, das öleganter zu lösen?

    Hier mal die Codes in VB:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class UniqueValidation
    2. Inherits ValidationRule
    3. Private _myData As MainModel 'Die Klasse, wo die Daten gehalten werden
    4. Public Overrides Function Validate(value As Object, cultureInfo As System.Globalization.CultureInfo) As System.Windows.Controls.ValidationResult
    5. _myData = CType(My.Application.FindResource("Root"), MainModel)
    6. Dim _row As Anreden = _
    7. CType(CType(value, BindingGroup).Items(0), Anreden)
    8. For Each temp As Anreden In _myData.context.Anreden
    9. If temp.Anrede = _row.Anrede Then
    10. Return New ValidationResult(False, "Den Wert existiert bereits")
    11. End If
    12. Next
    13. Return ValidationResult.ValidResult
    14. End Function
    15. End Class

    und XAML:
    Spoiler anzeigen

    XML-Quellcode

    1. <Window x:Class="MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. Height="350" Width="525"
    5. Title="MainWindow" DataContext="{Binding Source={StaticResource Root}}"
    6. xmlns:local="clr-namespace:DemoWPF" >
    7. <Window.Resources>
    8. <CollectionViewSource x:Key="Personenview" Source="{Binding Path=context.Personen}" />
    9. <CollectionViewSource x:Key="AnredenView" Source="{Binding Path=context.Anreden}" />
    10. </Window.Resources>
    11. <Grid>
    12. <Grid.RowDefinitions>
    13. <RowDefinition Height="Auto"/>
    14. <RowDefinition/>
    15. </Grid.RowDefinitions>
    16. <Grid.ColumnDefinitions>
    17. <ColumnDefinition/>
    18. <ColumnDefinition/>
    19. </Grid.ColumnDefinitions>
    20. <Button Grid.Column="0"
    21. Grid.Row="0"
    22. Command="{Binding Path=Laden}">Laden</Button>
    23. <Button Grid.Column="1"
    24. Grid.Row="0"
    25. Command="{Binding Path=Speichern}">Speichern</Button>
    26. <DataGrid Name="DG_Anreden"
    27. Grid.Column="0"
    28. Grid.Row="1"
    29. AutoGenerateColumns="false"
    30. IsSynchronizedWithCurrentItem="True"
    31. ItemsSource="{Binding Source={StaticResource AnredenView}}" >
    32. <DataGrid.RowValidationRules>
    33. <local:UniqueValidation ValidationStep="UpdatedValue" />
    34. </DataGrid.RowValidationRules>
    35. <DataGrid.Columns>
    36. <DataGridTextColumn Header="Anrede" Binding="{Binding Path=Anrede, ValidatesOnExceptions=True}" Width="0,5*"/>
    37. </DataGrid.Columns>
    38. </DataGrid>
    39. </Grid>
    40. </Window>


    Ich hab da bestimmt nen grobben Denkfehler drin.

    OT Eigentlich schade, dass es kein separates WPF-Forum gibs, weil is intressante Sache, das /OT

    Fielen Dank

    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    ich glaub du darfst nicht im DataContext suchen, sondern im CollectionView.

    Habich neulich die Entdeckung gemacht, dasses besser ist, die CollectionViews im Viewmodel anzulegen, nicht im Xaml.
    Obwohl CollectionView-Items eiglich nicht typisiert sind, hat man trotzdem im Xaml Designerunterstützung bei den Bindings.

    Damit entspricht ein ListCollectionView (denn ein solches musses sein) ziemlich genau der ollen BindingSource von WinForms, mit dem Vorteil, dasse nicht auffm Form rumliegt, sondern im Bereich der Daten, wenn du verstehst wassichmeine.
    Und da müsste man dann auch validierungsmäßig rankommen, hoffe ich (ich hab in Wpf noch nie was validiert).
    Also ich hab jetzt was gebastelt, ungefähr nach dem Schnittmuster von 4ViewsWpf.

    Nur habe ich im Mainmodel auch eine Public Shared Instanz angelegt, dass man von überall ins Mainmodel grabschen kann.
    (eiglich graust mich das zwar, aber den Locator-Pattern findich ebenso gräuslich, und Application.FindResources() noch gräuslicher).

    VB.NET-Quellcode

    1. Imports GalaSoft.MvvmLight
    2. Imports System.Collections
    3. Imports System.ComponentModel
    4. Imports System.IO
    5. Imports GalaSoft.MvvmLight.Command
    6. Public Class MainModel : Inherits ViewModelBase
    7. Public Shared _CodeInstance As MainModel
    8. Private _DataFile As New FileInfo("Data1.sdf")
    9. Public Property ReLoad As New RelayCommand( _
    10. Sub()
    11. If Context IsNot Nothing Then Context.Dispose()
    12. Context = New DataClasses1DataContext("Data Source=" & _DataFile.FullName)
    13. Context.Log = Console.Out
    14. If Not _DataFile.Exists Then Context.CreateDatabase()
    15. RaisePropertyChanged("Context")
    16. End Sub)
    17. Public Property Save As New RelayCommand( _
    18. Sub()
    19. Context.SubmitChanges()
    20. System.Media.SystemSounds.Asterisk.Play()
    21. End Sub)
    22. Public Property AddKunde As New RelayCommand( _
    23. Sub()
    24. 'Dim kd = New Kunde With {.Name = "Rumpelstilzchen"}
    25. 'Dim lst = DirectCast(Context.Kundes, IListSource).GetList
    26. 'lst.Add(kd)
    27. End Sub)
    28. Public Sub New()
    29. If ViewModelBase.IsInDesignModeStatic Then Return
    30. If _CodeInstance.NotNull Then Throw New Exception
    31. _CodeInstance = Me
    32. ReLoad.Execute(Nothing)
    33. End Sub
    34. Public Property Context As DataClasses1DataContext
    35. End Class
    Und die UniqueRule dann

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Public Class UniqueValidation : Inherits ValidationRule
    3. Public Overrides Function Validate(ByVal value As Object, ByVal cultureInfo As Globalization.CultureInfo) As ValidationResult
    4. Dim itm = DirectCast(DirectCast(value, BindingGroup).Items(0), Class1)
    5. Dim itm2 = DirectCast(MainModel._CodeInstance.Context.Class1s, IListSource).GetList.Cast(Of Class1).First(Function(x) x.Property1 = itm.Property1)
    6. Return If(itm Is itm2, ValidationResult.ValidResult, New ValidationResult(False, "Den Wert existiert bereits"))
    7. End Function
    8. End Class
    Also ich habe keine CollectionView, sondern binde direkt an den L2S-DataContext.

    XML-Quellcode

    1. <Window x:Class="MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:my="clr-namespace:ValidatedGridTester"
    5. xmlns:hlp="clr-namespace:System.Windows.Controls;assembly=WpfHelpers"
    6. xmlns:sys="clr-namespace:System;assembly=mscorlib"
    7. Title="MainWindow" Height="350" Width="525"
    8. DataContext="{StaticResource MainModel}">
    9. <!--
    10. -->
    11. <hlp:GridEx>
    12. <Grid.ColumnDefinitions>
    13. <ColumnDefinition MinWidth="30" Width="*" />
    14. </Grid.ColumnDefinitions>
    15. <Grid.RowDefinitions>
    16. <RowDefinition Height="Auto" />
    17. <RowDefinition Height="*" />
    18. </Grid.RowDefinitions>
    19. <Menu>
    20. <MenuItem Header="ReLoad" Command="{Binding Path=ReLoad}" />
    21. <MenuItem Header="Save" Command="{Binding Path=Save}" />
    22. <MenuItem Header="AddKunde" Command="{Binding Path=AddKunde}" />
    23. </Menu>
    24. <DataGrid ItemsSource="{Binding Path=Context.Class1s}" hlp:GridEx.Range="a2" AutoGenerateColumns="False">
    25. <DataGrid.Columns>
    26. <DataGridTextColumn Header="Property1" Binding="{Binding Path=Property1}" />
    27. </DataGrid.Columns>
    28. <DataGrid.RowValidationRules>
    29. <my:UniqueValidation ValidationStep="UpdatedValue" />
    30. </DataGrid.RowValidationRules>
    31. </DataGrid>
    32. </hlp:GridEx>
    33. </Window>
    Ich finde immer wieder - Wpf ist doch ziemlich der Krampf.
    Sone Casterei darf doch nicht wahr sein, und dass eine Validation-Rule eine ganz unabhängige Klasse sein muß, ohne jeden Bezug zum Datenmodell ist doch auch Brainfuck - was für Kapriolen das erzwingt!
    (Und Xml-Syntax ist insgesamt die Ausgeburt an Redundanz, und ...)

    So, ich probier noch mittm ListCollectionView
    Naja, je mehr man sich mit dieses WPF auseinandersetzt, desto abschreckender find ich das. Da ist doch son Dataset in einer normalen Form-Anwendung deutlich einfacher zu handeln. Das betrifft auch die Validierung, weil da son Fehleintrag bereits im Datagridview Dataerror auslöst und gleich entsprechend behandelt werden kann. Im vorliegenden Fall hatt ich den Eintrag gleich gelöscht und bin in die vorhandene Zeile gesprungen (also nich ich sondern die Bindingsource).
    Bei WPF verliere ich immer ziemlich schnell den Überblick.
    Und so einfach wie bei dir kann ich gar nicht auf Mainmodel zugreifen !? Irgendwie erzeugt des immer ne andere Insatnz, so das Mainmodel.context Nothing ist.
    MainModel:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class MainModel
    2. Public Shared Root As MainModel
    3. Public Sub New()
    4. End Sub
    5. Public Property context As MyDataDataContext
    6. Private _DataFile As New FileInfo("MyDB.sdf")
    7. 'Command DB Laden
    8. Public Property Laden As New RelayCommand( _
    9. Sub()
    10. If context IsNot Nothing Then context.Dispose()
    11. context = New MyDataDataContext("Data Source=" & _DataFile.FullName)
    12. context.Log = Console.Out
    13. If Not _DataFile.Exists Then
    14. context.CreateDatabase()
    15. End If
    16. OnPropertyChanged("context")
    17. End Sub)
    18. 'Command DB Speichern
    19. Public Property Speichern As New RelayCommand(Sub() context.SubmitChanges())
    20. End Class


    Application XAML:
    Spoiler anzeigen

    XML-Quellcode

    1. <Application x:Class="Application"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. StartupUri="MainWindow.xaml"
    5. xmlns:my="clr-namespace:DemoWPF" >
    6. <Application.Resources>
    7. <my:MainModel x:Key="Root"/>
    8. </Application.Resources>
    9. </Application>

    Und schließlich MainWindow XAML:
    Spoiler anzeigen

    XML-Quellcode

    1. <Window x:Class="MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. Height="350" Width="525"
    5. Title="MainWindow"
    6. xmlns:local="clr-namespace:DemoWPF" DataContext="{Binding Source={StaticResource Root}}">
    7. <Window.Resources>
    8. <CollectionViewSource x:Key="Personenview" Source="{Binding Path=context.Personen}" />
    9. <CollectionViewSource x:Key="AnredenView" Source="{Binding Path=context.Anreden}" />
    10. </Window.Resources>

    Mainwindow VB
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Class MainWindow
    2. Sub ButtonClick()
    3. ' Hier gibs trotz geladener Daten ein ObjektverweisException
    4. #Also context is Nothing
    5. For Each t As Anreden In MainModel.Root.context.Anreden
    6. Debug.Print("Anrede = " & t.Anrede)
    7. Next
    8. End Sub
    9. End Class

    Und das versteh ich nicht, weil ja Root Shared ist. Irgendwie greift das alles nicht wirklich über diese Shared Root auf Context sondern direkt über eine Instanz von Mainmodul, die in Application.XAML erzeucht wird. Versuche ich dort als Resource Mainmodel.Root anzugeben, sachter, dass Mainmodel nicht über eine Eigenschaft Root verfügen tut. ?(
    Allerdings wird im MainWindow über Application.Resource auf Root zugegriffen.... Rätzel über Rätzel.

    Ich denke fast, ich lass des mit WPF. Wirkliche Vorteile kann ich da nicht erkennen :thumbdown: mit dieser wüsten Binding-Sch...
    Ich bin schwer frustriert. Vor allem findich die Doku so ätzend. Keine Eigenschaftenbeschreibung, Kein Objektkatalog, winziges XAML Fensterle...

    Aber wenn du mir noch meinen Fehler von hier oben erklären könntest, wär das vielleicht noch mal eine Weiterbeschäftigung wert.

    Schönes Wochenende

    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:

    Vatter schrieb:

    Aber wenn du mir noch meinen Fehler von hier oben erklären könntest, wär das vielleicht noch mal eine Weiterbeschäftigung wert.
    meinst du den?
    Public Shared Root As New MainModel




    Hier wies bei mir funzte.
    Enthält meine neueste Erfindung zum Mainmodel-Problem: ViewModelBase(Of T)
    Und 2 Extensions, die die Casterei vereinfachen.

    Und ein Grid ist direkt an den Context gebunden, und das annere an eine ListCollectionView.

    Übrigens kann man typDataset so leidlich auch in Wpf verwenden, nur leider nicht mit DataTemplates.
    Dateien

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Morgen Erfinder,
    Naja, New hatte ich schon gehabt. Zugriff aus MainWindow mit Mainmodel.Root ging trotzdem ins Nirwana (siehe oben) Es gibt offenbar eine weitere Instanz der MainWindow-Klasse, deren context-Property (die ja nicht Shared ist) in den Datagrids korrekt auftaucht.

    Allerdings muß ich gestehen, dass ich kein ViewModelBas drinhabe. Ich vermute mal, das hängt mit der MVVM Gschichte zusamm? Ich hab den Sinn dieser ViewModelBase mit meinem beschränkten Geist noch nicht erkannt. Bei MSDN gibs nur ne "Vorschau für vb2012". Dem entnehme ich, dass Viewmodel die PropertyChanged-Events feuert und so Zeugs..?
    Dafür hab ich INotivyPropertyChanged importert und das Event in Mainmodel drin. Die Aktualisierung zur Form funzt mit dieser "einfachen" Variante zumindest.

    Danke schonmal für dein GridTester-Projekt,
    werd ich mir nach Feierabend mal reinziehen.
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:

    Vatter schrieb:

    Es gibt offenbar eine weitere Instanz der MainWindow-Klasse,
    Jo, dassis offenbar.
    Wenn man dein Application.Xaml anguckt.

    XML-Quellcode

    1. <my:MainModel x:Key="Root"/>
    erstellt eine neue Instanz der MainModel-Klasse.
    Ich dachte du tätest ans static Root-Feld der MainModel-Klasse binden, wie etwa in WpfTreeview-Tut gezeigt.
    Ach - crap! - Dort binden ja die Windows nicht an eine StaticResource in App.Xaml, sondern direkt ans static Feld:

    XML-Quellcode

    1. <Window x:Class="MainWindow"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. Title="MainWindow" Height="350" Width="525"
    5. xmlns:my="clr-namespace:WpfFilesystemTreeView"
    6. DataContext="{x:Static my:MainModel.Root}">
    Und das ist auch kein Binding, sondern die direkte Zuweisung des Feldes an den DataContext.

    Sowas kann man inne App.Xaml garnet machen, sone Resource anlegen.

    Also meine ViewmodelBase-Erfindung ist schon wirklich nicht schlecht, scheint mir (jaja - eigenlob stinkt, aber stinke isja Geschmackssache :D)
    Und Wpf ist wirklich verquast. ?(
    Großes AHA!
    Ich hab immer bei der Datacontext-Einstellung unter Databinding statt Resourcen geschaut, weil bei den Resourcen halt Farben, Fonts u.dgl. angeboten werden. den Eintrag "lokal >> Root" hab ich total übersehen. Damit ist mein Instanz-Problem behoben und es wird (fast) alles so ausgeführt wie vorgesehen.
    Nur die Validierungsklasse ist nach wie vor merkwürden zu mir:
    Existiert der Eintrag bereits, wird dies im Datagrid entsptrechend angezeigert, geb ich einen neuen Wert ein, sagt er mir, dass die Sequenz keinen Eintrag enthält. Ich seh darin keinen Fehler, der Debugger aber schon (siehe Bild im Anhang). Es ist zum Auswachsen. Immer wenn ich glaube, was verstanden zu haben, kömmt sowas. :cursing:

    itm2 ist zu diesem Zeitpunkt noch Nothing, weil er die Zeile nicht mehr vollständig ausführt. MainModel.Root.context.Anreden enthält lt. Überwachung die vollständige Tabelle...

    Hüülfäää
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Also Sry,
    ich raffs immer noch nicht:
    Bei dir ist App.XAML

    XML-Quellcode

    1. <Application.Resources>
    2. <my:MainModel x:Key="MainModel" />
    3. </Application.Resources>
    MainWindow.XAML

    XML-Quellcode

    1. Title="MainWindow" Height="350" Width="525"
    2. DataContext="{StaticResource MainModel}">
    und es Ding läuft.

    Bei mir ist des so, damit (inkl. Validierung) alles funktioniert
    App.XAML

    XML-Quellcode

    1. <Application.Resources>
    2. <my:MainModel x:Key="MainModel"/>
    3. </Application.Resources>
    MainWindow.XAML

    XML-Quellcode

    1. DataContext="{x:Static my:MainModel.Root}">

    Dabei ist bei DataContext="{x:Static my:MainModel.Root}"keinerlei Designerunterstützung verfügbar :thumbdown:
    Meine MainModel-Klasse hat ja die Shared Root as MainModel, also muss ich ja nu mal da drauf zugreifen.
    Was bitte ist jetzt der Unterschied zwischen {StaticResource MainModel} und {x:Static my:MainModel.Root}? Beide Formulierungen greifen doch auf die von App.XAML erzeugte MainModel-Instanz zu oder? Nur dass bei der 2. Variante noch auf Root zugegriffen werden kann/wird.

    ?(
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:

    XML-Quellcode

    1. <Application.Resources>
    2. <my:MainModel x:Key="MainModel" />
    3. </Application.Resources>
    Das ist eine MainModel-Instanz in den Application-Resources

    XML-Quellcode

    1. DataContext="{StaticResource MainModel}"
    Das greift auf diese Resource zu.

    XML-Quellcode

    1. DataContext="{x:Static my:MainModel.Root}"
    Das greift nicht auf die Application-Resource zu, sondern direkt in den Typ MainModel, auf dessen Public Shared Member (Feld oder Property) "Root".

    Also wenn du einerseits in den Application.Resources ein Mainmodel anlegst, dann aber im Window auf den Shared "Root"-Member des Mainmodel-Typs zugreifst, dann bist du mit 2 verschiedenen Mainmodel-Instanzen unterwegs, und hast also ein Proplem.
    Komisch, dasses trotzdem funzt...
    Das würde ja eigentlich heißen, wenn ich nur 1 App-weite Instanz haben wollte, müßte ich den Root-Member einfach wechlassen und würde denn mit der lokalen und einzigen Instanz aus den App-Resources arbeiten.
    Wenn ich nun aber in VB-Code auf diese Instanz zugreifen wollte geht das nur, indem ich mir diese wie folgt besorge:

    VB.NET-Quellcode

    1. Dim m As MainModel = CType(My.Application.FindResource("MainModel"), MainModel)

    Oder gibs noch ne andere Möglichkeit, da ran zu kommen ohne dies FindResources-Gedöns? Also zumindest sind dann alle Änderungen im Datagrid sofort aktualisiert.
    Aus deinem Beispielprojekt lese ich soviel heraus, dass die ViewModel-Klasse ausm Galasoft dir diese Instanz besorgt und zur Verfügung stellt (MainModel.Instanz....). Ich find des da nur so doof, dass der Designer da so garnix mehr sagt. Mit dem Designer aus VB ist man (sry bin ich) da völlig außen vor. Verwendest du einen anderen Designer für die Benutzeroberfläche?
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    ja, dassis ja grad meine Erfindung mitte MainModelBase, von der ich fürderhin alle meine MainModels erben lasse. Die stellt dann eine Art Singleton für den Zugriff per Code bereit, und die Singleton-Instanz ist dieselbe wie die im Xaml.
    Gugge zB. DelegateConverter
    (Also konkret die Sample-Solution angugge, weil im Tut verbreiter ich mich nicht dazu)
    Ja also,
    ich habe mein Projekt jetzt so hinbekommen/hingewerkelt, dass ich eine Instanz des MainModel applikationsweit sowohl über XAML (lokale Resource) als auch über VB erreichen kann. Ich habe einfach in der App-VB eine Shared DataInstanz as MainModel erstellt und dieser im StartUp-Event eine Referenz über My.Application.FindResource("MainModel") zugewiesen.
    Damit bekomm ich meine weiteren Versuche mit Validation, Datenanzeige usw. supi gehandelt.
    Ich hoffe, dass mein Vorgehen nicht zu unsauber ist, aber ich sehe im Moment für mich erstma keine einfachere Möglichkeit.
    Wenn ich mein Projekt soweit aufbereitet hab, werd ich es mir als Vorlage exportieren und hier reinstellen, vielleicht intressierts ja jemanden....

    Vielen Dank EDR

    Üprigens: Schade dasses hier kein WPF-Forumsbereich geben tut. (sagtich das schonmal?)
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:

    Vatter schrieb:

    im StartUp-Event eine Referenz über My.Application.FindResource("MainModel") zugewiesen.
    Auch ne gute Idee, findich. :thumbsup:
    Wie gesagt: In meinen Augen fehlts dem Wpf an vielen Stellen an komfortablen Konzepten, und da bastelt sich teilweise jeder dann iwas hin, mehr oder weniger schön.
    Deine Lösung bewirkt ja auch, dass nur ein einziges mal dieses häßliche .FindResource() und DirectCast ausgeführt werden muß, und danach ist dein Mainmodel ja auch sowohl im Xaml als auch im Code überall verfügbar, und das (Redundanzfreiheit) ist ja die Hauptsache.