DataGrid Zeilen nummerieren / .FindName klappt nicht

  • WPF

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von eichseinet.

    DataGrid Zeilen nummerieren / .FindName klappt nicht

    Hallo zusammen!

    Bei Microsoft habe ich ein Beispiel gefunden, um die Zeilen eines DataGrids zu nummerieren. Solange das Grid im MainWindow sitzt klappt das auch.
    In meinem Projekt befindet sich im MainWindow aber ein TabControl, in dem dann ein UserControl liegt, das dann die eigentliche Tabelle enthält.

    MainWindow XAML

    XML-Quellcode

    1. <Grid>
    2. <TabControl >
    3. <TabItem Header="Tab01">
    4. <local:Tab01_UserControl_mit_DataGrid/>
    5. </TabItem>
    6. </TabControl>
    7. </Grid>


    UserControl XAML

    XML-Quellcode

    1. <Grid>
    2. <Grid.Resources>
    3. <local:ConvertItemToIndex x:Key="IndexConverter"/>
    4. </Grid.Resources>
    5. <DataGrid x:Name="Grid01" ItemsSource="{Binding Coll}">
    6. <DataGrid.RowHeaderStyle>
    7. <Style TargetType="{x:Type DataGridRowHeader}">
    8. <Setter Property="Content" Value="{Binding Converter={StaticResource IndexConverter}}" />
    9. </Style>
    10. </DataGrid.RowHeaderStyle>
    11. </DataGrid>
    12. </Grid>


    Code des Converters

    VB.NET-Quellcode

    1. Public Class ConvertItemToIndex
    2. Implements IValueConverter
    3. Public Function Convert(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
    4. Try
    5. 'Get the CollectionView from the DataGrid that is using the converter
    6. Dim dg As DataGrid = DirectCast(Application.Current.MainWindow.FindName("Grid01"), DataGrid)
    7. Dim cv As CollectionView = DirectCast(dg.Items, CollectionView)
    8. 'Get the index of the item from the CollectionView
    9. Dim rowindex As Integer = cv.IndexOf(value) + 1
    10. Return rowindex.ToString()
    11. Catch e As Exception
    12. Throw New NotImplementedException(e.Message)
    13. End Try
    14. End Function
    15. Public Function ConvertBack(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
    16. Throw New NotImplementedException()
    17. End Function
    18. End Class


    Liegt das DataGrid wie hier beschrieben im UserControl, dann ist "dg", also das gefundene DataGrid, im Converter Nothing und in der nächsten Zeilen erscheint dann natürlich ein Fehler.
    Verschiebe ich das DataGrid direkt ins MainWindow, dann funktioniert es. Alle Versuche die Suche nach dem DataGrid direkt auf das UserControl umzustellen schlugen fehl. Hat jemand eine Idee was man da ändern muss?
    Alternativen sind auch willkommen. Das DataGrid soll einfach immer von oben nach unten durchgehend nummeriert sein. Auch wenn es sortiert oder gefiltert wurde.

    Gruß

    eddi
    Also wenn es darum geht, dass er die Hierarchie nicht erkennt, wenn es im TabItem im TabControl liegt, es aber erkennt, wenn es im MainWindow liegt - Folgender Vorschlag:

    Implementiere im UserControl eine DependencyProperty - Zum Beispiel GridName und GridNameProperty - und binde den Namen des Grids an diese Property.
    Setze diese Property im XAML im Tab-Control im UserControl. Denn dann ist dieser Name im Main-Frame definitiv vorhanden.

    Im Augenblick - so liest es sich - will der Converter die Variable "Grid01" finden, die ist in der reinen Anwendung aber nicht definiert, sondern wird erst definiert, wenn du das UserControl einbindest, was aber zu Problemen führen kann. Wenn du aber so rum bindest, kannst du das Grid auch immer aus dem Main-Frame ansprechen, da die Variable dort bereits existiert.

    BTW: Es hat noch den zweiten Vorteil, dass du dein UserControl wiederverwendbarer gestaltest, denn angenommen du baust ein zweites UC ein, dann haben beide eine Variable, die Grid01 heißen würden. Wenn du den Namen aber über eine DP bindest, ist es variabler einsetzbar. Gleiches gilt übrigens auch für die Property, die du an den Converter bindest.
    Binde sie an eine Backend DependencyProperty, dann kannst du sie im XAML bei MainWindow über diese Property ansprechen und dort an den Converter binden.
    nein - nicht ein UserControl bauen, mit DepProp und so.
    Was du brauchst ist ein geeigneter ValueConverter.
    Der ValueConverter, den du hast, ist schon ganz schön, aber definitiv ungeeignet, weil er nur dieses Grid behandeln kann:

    VB.NET-Quellcode

    1. Dim dg As DataGrid = DirectCast(Application.Current.MainWindow.FindName("Grid01"), DataGrid)
    Das ist hardcoded GruselCode, und für diese Zeile eine flexible Alternative zu finden halte ich für dein Problem.

    Ich bin in Wpf inzwischen ziemlich ungeübt, aber ich glaub ziemlich sicher, dass das möglich ist, auch mit vertretbarem Aufwand.
    Auffm ersten Blick siehts mir sogar ziemlich einfach aus - aber bei Wpf sieht vieles anders aus als auf den ersten Blick.

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

    @ErfinderdesRades: Genau die Zeile würd ich gerne abändern, wenn ich's könnte. Am besten wäre wie gesagt statt der Suche einfach das als Parameter hereingereichte DataGrid. Klappen wills aber nicht.

    XML-Quellcode

    1. ConverterParameter={Binding Propertyname, ElementName=Grid01}

    Auf die Art kommt man ja nur an ein Property ran. Es müsste aber das ganze Object gesendet werden.

    @PadreSperanza: Bin mir gar nicht mehr so sicher, ob ich deinen Tipp überhaupt richtig verstanden habe.

    XML-Quellcode

    1. <DataGrid x:Name="Grid01" ItemsSource="{Binding Coll}" local:DependencyPropertyGrid.GridName="">


    VB.NET-Quellcode

    1. Public Class DependencyPropertyGrid
    2. Public Shared Function GetGridName(ByVal element As DependencyObject) As Object
    3. If element Is Nothing Then
    4. Throw New ArgumentNullException("element")
    5. End If
    6. Return element.GetValue(GridNameProperty)
    7. End Function
    8. Public Shared Sub SetGridName(ByVal element As DependencyObject, ByVal value As Object)
    9. If element Is Nothing Then
    10. Throw New ArgumentNullException("element")
    11. End If
    12. element.SetValue(GridNameProperty, value)
    13. End Sub
    14. Public Shared ReadOnly GridNameProperty As _
    15. DependencyProperty = DependencyProperty.RegisterAttached("GridName",
    16. GetType(String), GetType(DependencyPropertyGrid),
    17. New PropertyMetadata(Nothing, AddressOf TEST))
    18. Private Shared Sub TEST(d As DependencyObject, e As DependencyPropertyChangedEventArgs)
    19. 'und nu?
    20. End Sub
    21. End Class


    So sieht das Attached DependencyProperty aus und wie oben gezeigt ist es am DataGrid eingebunden. Aber was genau meinst Du jetzt mit dem "den Namen daran binden"?

    eddi

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „eichseinet“ ()

    Ja, ich muss zugegben, ich habe mich am Anfang etwas vertan, du brauchst nicht den Namen, sondern du musst deinen Content binden, damit du den vergeben kannst. Deshalb ändere das Binding des Namens in ein ContentBinding. Hab es mal aufgezeigt, wie ich es meine:

    Du hast ein UserControl. Dieses UserControl hat ja ebenfalls eine Code-Behind Seite. In der heftest du

    VB.NET-Quellcode

    1. Public Shared Function GetGridContentName(ByVal element As DependencyObject) As Object
    2. If element Is Nothing Then
    3. Throw New ArgumentNullException("element")
    4. End If
    5. Return element.GetValue(GridContentProperty)
    6. End Function
    7. Public Shared Sub SetGridContent(ByVal element As DependencyObject, ByVal value As Object)
    8. If element Is Nothing Then
    9. Throw New ArgumentNullException("element")
    10. End If
    11. element.SetValue(GridContentProperty, value)
    12. End Sub
    13. Public Shared ReadOnly GridContentProperty As _
    14. DependencyProperty = DependencyProperty.RegisterAttached("GridContent",
    15. GetType(CONTENT_TYPE), GetType(USERCONTROL_TYPE),
    16. New PropertyMetadata(Nothing))


    das dran - Wobei CONTENT_TYPE der Type ist, den Content in deinem User Control haben soll, also der Content, der in einem DataGrid drin ist.
    USERCONTROL_TYPE ist der Name deines UserControls (So wie auch die Klasse des UserControls heißt), die New PropertyMetadata füllst du nur mit Nothing, da sie jetzt direkt dem UserControl angehört und keiner externen Klasse.

    Sobald du das gemacht hast, kannst du in XAML deines Grids sagen:

    XML-Quellcode

    1. ...
    2. <Grid>
    3. <DataGrid x:Name="Grid01" ItemsSource="{Binding Coll}">
    4. <DataGrid.RowHeaderStyle>
    5. <Style TargetType="DataGridRowHeader">
    6. <Setter Property="Content" Value="{Binding GridContent, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Tab01_UserControl_mit_DataGrid}}, Converter={StaticResource IndexConverter}}"/>
    7. </Style>
    8. </DataGrid.RowHeaderStyle>
    9. </DataGrid>
    10. </Grid>



    Sobald du das hast, kannst du das in der MainWindow so ansprechen:

    XML-Quellcode

    1. <Grid>
    2. <TabControl >
    3. <TabItem Header="Tab01">
    4. <local:Tab01_UserControl_mit_DataGrid x:Name="UC" GridContent="XXX"/>
    5. </TabItem>
    6. </TabControl>
    7. </Grid>


    und hier kannst du nun mittels XXX Deine Daten übergeben als DataGrid und müsstest die Zeile aus dem Converter Dim dg As DataGrid = DirectCast(Application.Current.MainWindow.FindName("Grid01"), DataGrid) entfernen können, weil im Converter jetztt das DataGrid "Value" ist. Müsste also so aussehen:


    VB.NET-Quellcode

    1. Public Class ConvertItemToIndex
    2. Implements IValueConverter
    3. Public Function Convert(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
    4. Try
    5. 'Get the CollectionView from the DataGrid that is using the converter
    6. Dim cv As CollectionView = DirectCast(value.Items, CollectionView)
    7. 'Get the index of the item from the CollectionView
    8. Dim rowindex As Integer = cv.IndexOf(value) + 1
    9. Return rowindex.ToString()
    10. Catch e As Exception
    11. Throw New NotImplementedException(e.Message)
    12. End Try
    13. End Function
    14. Public Function ConvertBack(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
    15. Throw New NotImplementedException()
    16. End Function
    17. End Class


    So zumindest der theoretische Aspekt. Es kann sein, dass ich mich verzettelt habe, aber ich bin seit 4 Uhr auf den Beinen und hatte einen langen Arbeitstag... Aber so zumindest nutzt WPF Converter derart, dass du die Quelle, die genutzt werden soll als Value angeben kannst

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

    Vollzitat des direkten Vorposts an dieser Stelle entfernt ~VaporiZed

    Ja, kann man dann sicherlich auch, daran habe ich nicht gedacht. :D

    Ich habe mich nur die letzten Wochen mit DependencyProperties rumgeschlagen und der Weg ging bei mir immer, dass ich alles über diesen Weg gehe. So habe ich im CodeBehind immer den Zugriff darauf gesichert und kann es auch mal austauschen, falls ich ein anderes Grid dran binden möchte und das alles nur mittels schnellem Austausch der gebundenen Variablen

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

    Am Sonntag hab ich um 18:30 genervt abgebrochen, weil ich nicht weiter kam und gestern fehlte leider die Zeit...
    @ErfinderDesRades: Leider funktioniert im ConverterParameter wohl gar kein Binding, wie ich inzwischen gelesen hab. Das Beispiel war eher allgemein gedacht und gar nicht im Visual Studio getestet. Diese Idee von mir ist also leider ein Flop.

    @PadreSperanza: Leider ist dieser Ansatz auch ein Flop. Habs nach deiner Methode noch gar nicht hinbekommen, aber nachfragen nützt nix. Denn:

    XML-Quellcode

    1. <Setter Property="Content" Value="{Binding ElementName=Grid01, Converter={StaticResource IndexConverter}}"/>

    so liefert XAML mir das DataGrid als Value in den Converter (das war ja der Plan). Kam ich eben drauf, dass ja schließlich das gebundene Element als Value reinkommt. Das Dumme ist nur, dass im Original bereits die aktuelle Zeile als Value reinkommt und ja auch hier benötigt wird.

    VB.NET-Quellcode

    1. Dim rowindex As Integer = cv.IndexOf(value) + 1


    Kommt statt der Zeile das ganze DataGrid als Value rein, dann klappt das natürlich nicht mehr und der Converter gibt immer 0 zurück.
    Allmählich seh schwarz für die Zeilennummern.

    P.S. Das die WPF das DataGrid nicht findet liegt wohl auch nicht am Zeitpunkt des Zugriffs. Ein Button der die Suche nach dem DataGrid auslöst findet es nämlich auch nicht. Es liegt also an der Struktur, bzw. einem für diesen Aufbau falschen Ansatz zur Suche.

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

    Gestern hatte ich mit der WPF nochmal ein längeres Streitgespräch. Wir sind dann so verblieben, dass die Wpf weiterhin keinen Zugriff auf das DataGrid gewährt. Daher muss sie sich jetzt mit meinem extrem gruseligen Code abfinden.
    Zuerst werden in der Applicatioin ein DataGrid und ein Event deklariert und eine Sub feuert dann das Event.
    Application

    VB.NET-Quellcode

    1. Public Shared DataGrid_Aufnahmen As DataGrid
    2. Public Shared Event Grid_holen_Event()
    3. 'Sub wird aus dem Converter aufgerufen
    4. Public Shared Sub Grid_holen()
    5. RaiseEvent Grid_holen_Event()
    6. End Sub


    UserControl CodeBehind

    VB.NET-Quellcode

    1. Private Sub Aufnahmen_UC_Initialized(sender As Object, e As EventArgs) Handles Me.Initialized
    2. Me.DataContext = Aufnahmen
    3. AddHandler Grid_holen_Event, AddressOf Grid_senden
    4. End Sub
    5. Private Sub Grid_senden()
    6. Application.DataGrid_Aufnahmen = Aufnahmen_DataGrid 'Name des DataGrids, wird hier an die globale Variable übergeben
    7. End Sub


    Nun der Converter

    VB.NET-Quellcode

    1. Public Class ConvertItemToIndex
    2. Implements IValueConverter
    3. Public Function Convert(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
    4. Try
    5. 'Get the CollectionView from the DataGrid that is using the converter
    6. Application.Grid_holen() 'Function, die ein Event ans UserControl feuert, von da wird dann das DataGrid an die shared Variable in der Application gesendet
    7. Dim DGInstanz As DataGrid = Application.DataGrid_Aufnahmen
    8. Dim cv As CollectionView = DirectCast(DGInstanz.Items, CollectionView)
    9. 'Get the index of the item from the CollectionView
    10. Dim rowindex As Integer = cv.IndexOf(value) + 1
    11. Return rowindex.ToString()
    12. Catch e As Exception
    13. Throw New NotImplementedException(e.Message)
    14. End Try
    15. End Function
    16. Public Function ConvertBack(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
    17. Throw New NotImplementedException()
    18. End Function
    19. End Class


    und der eingebundene Converter

    XML-Quellcode

    1. <local:ConvertItemToIndex x:Key="Index"/>
    2. <Style TargetType="{x:Type DataGridRowHeader}">
    3. <Setter Property="Content" Value="{Binding Converter={StaticResource Index}}" />
    4. <Setter Property="Width" Value="35"/>
    5. </Style>

    Ist jetzt nur als Style eingebunden, weil das DataGrid dann etwas übersichtlicher bleibt und sich die Breite auch gleich anpassen lässt.

    Ist im UserControl auch eine DesigntimeInstanz angelegt, dann beschwert sich die WPF, dass nicht auf eine Instanz gebunden wurde.
    Kann sie. Wenn sie dermaßen bockig ist beim Zugriff auf Daten/Controls, dann muss sie jetzt damit leben.
    Der Converter muss bei dieser Methode natürlich für jedes DataGrid neu angelegt werden und auch die Variablen und Events. Ist mir jetzt aber auch wurscht!
    Die Numerierung ist immer fortlaufen; auch nach Sortierung und Filterung.
    Irgendwann probier ich's vielleicht nochmal mit ner anderen Lösung; aktuell bleibt das so. Außer es fällt jemandem von euch noch etwas weniger brutales ein.

    Gruß
    eddi
    @ErfinderDesRades: Wenn's schnell gehen soll... dann klappt einfach nix.
    Das Testprojekt enthält jetzt gleich 2 Tabs mit je einer Tabelle. Alles wurde 2 mal angelegt.
    Zusätzlich werden im CodeBehind (weils da für den Test am simpelsten zu lösen war) Daten aus Tabelle 2 nach Tabelle 1 kopiert. Soll verdeutlichen, warum SHARED Instanzen in der Application angelegt sind. Anders konnte ich noch keinen Datenaustausch zw. vorhandenen Klassen hinbekommen.

    Vielen Dank schon mal im Voraus.

    Gruß
    eddi
    Dateien
    Jo, das sind ja schöne Umständlichkeiten, die du da unternimmst, quasi von hinten durch die Brust ins Auge und nochmal unter der Achselhöhle durch ;)
    Wpf lässt einen da leicht ins Dickicht laufen - wenn man da keine durchdachte Architektur hat...
    Ich könnte das Aufbauen nach dieser Architektur: Grundlagen - MVVM-Anwendungs-Struktur
    Damit wärs glaub kein Thema, dem Converter beizubringen, wassersoll.
    Aber das wäre ein Komplett-Umbau und eine strategische Neu-Orientierung...
    Darum hab ich mal den kompletten Aufbau gesendet, um das alles mal zu zeigen. Mein Problem war und ist einfach der Zugriff über Klassen hinweg auf die Daten. Unter Win Forms waren die global und man kam immer an alles ran.
    In den eigentlichen Projekt gibts 7 Tabs mit je einem DataGrid. Darin liegen unterschiedlichen Daten, die zu größten Teil in Tab01 zur Verarbeitung benötigt werden. (Angaben zu TV-Sendern, gewünschte Vor- und Nachlaufzeiten einer TV-Aufnahme, Ordnerliste, Einstellungen...)
    Im 1. Tab wird dann aus den aktuellen Daten einer Sendung mit den Vorgaben aus den anderen Tabellen eine Aufnahme erstellt.
    Das Problem war immer, wie lassen sich die Daten in verschiedene Tabs und DataGrids aufteilen und trotzdem aus den anderen Tabs darauf zugreifen? CodeBehind ist für kein Tabu. Das Programm wurde nur in eigene Klassen gepackt, um das Projekt übersichtlicher zu gestalten. So liegt nicht ein Teil desCodes im CodeBehind und allgemein gültige Teile wieder in eigenen Dateien.
    Mir ist bewusst, dass mein Programmaufbau sehr ungewöhnlich ist. Leider hab ich es auch nach wirklich sehr langer Zeit nicht besser hinbekommen. Deine Tuturials zu MVVM wurden zu Beginn auch mehrmals angesehen. Damit kam ich aber leider nicht auf den für mich nötigen Aufbau. (heisst nicht, dass es nicht geht, nur ich konnte es halt nicht)
    Wenn Du dir wirklich die Mühe machst das alles nach MVVM umzubauen und dabei der Zugriff auf benachbarte Klassen erhalten bleibt, dann wär ich echt sehr dankbar und könnte dieses Eigenkonstrukt endlich abschütteln!

    Gruß
    eddi
    Ich kann Wpf nicht ohne meine HelpersBibliotheken.
    Dank dieser gibts bei mir zB eigentlich überhaupt keine Converter mehr.
    Ich habe eine DelegateConverter-Klasse, die individuelle IConverter-Entwicklung erübrigt - so ähnlich wie RelayCommand individuelle ICommand-Implementiererei unnötig macht.
    Das zeigt sich hier als enorm nützlich, denn da der Conversion-Delegat (an den mein DelegateConverter gebunden wird) im MainModel liegt muss man da kein Tänzchen veranstalten, um dem die CollectionView beizubringen, die er nachgucken soll.
    Weil CollectionView und Conversion-Delegat liegen im selben MainModel - gibt ja nur eins :D

    Also Xaml:

    XML-Quellcode

    1. <UserControl x:Class="View.Tab01_UC"
    2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    5. mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    6. xmlns:hlp="clr-namespace:System.Windows.Controls;assembly=WpfHelpers"
    7. xmlns:vm="clr-namespace:ZeilenNummern.Viewmodel"
    8. xmlns:vw="clr-namespace:ZeilenNummern.View"
    9. DataContext="{Binding Source={x:Static vm:Mainmodel.Instance}}">
    10. <!--
    11. -->
    12. <Grid>
    13. <DataGrid x:Name="Tab01_Grid" ItemsSource="{Binding Daten01_Klasses}" >
    14. <FrameworkElement.Resources>
    15. <hlp:DelegateConverter x:Key="Index" Conversion="{Binding Source={x:Static vm:Mainmodel.Instance}, Path= Daten01_Klasses_Indicees, Mode=OneWay}" />
    16. </FrameworkElement.Resources>
    17. <DataGrid.RowHeaderStyle>
    18. <Style TargetType="{x:Type DataGridRowHeader}">
    19. <Setter Property="Content" Value="{Binding Converter={StaticResource Index}}" />
    20. </Style>
    21. </DataGrid.RowHeaderStyle>
    22. </DataGrid>
    23. </Grid>
    24. </UserControl>

    MainModel:

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Imports System.Collections.ObjectModel
    3. Imports System.Reflection
    4. Namespace Viewmodel
    5. Public Class Mainmodel : Inherits NotifyPropertyChanged
    6. Public Shared Instance As New Mainmodel
    7. Private __Daten01_Klasses As New ObservableCollection(Of Daten01_Klasse)()
    8. Public Property Daten01_Klasses() As ListCollectionView = DirectCast(CollectionViewSource.GetDefaultView(__Daten01_Klasses), ListCollectionView)
    9. Private Sub New()
    10. If IsInDesignMode Then GenerateDaten01_Klasses()
    11. End Sub
    12. 'Property to bind at a DelegateConverter.Conversion
    13. Public ReadOnly Property Daten01_Klasses_Indicees() As Func(Of Object, Object) = Function(o)
    14. Dim rowindex As Integer = Daten01_Klasses.IndexOf(o) + 1
    15. Return rowindex.ToString()
    16. End Function
    17. Private Sub GenerateDaten01_Klasses()
    18. Call 10.Times.From(__Daten01_Klasses.Count, Sub(i) __Daten01_Klasses.Add(New Daten01_Klasse With {.Wert01 = "Wert01_" & i, .Wert02 = "Wert02_" & i}))
    19. End Sub
    20. End Class
    21. End Namespace
    Ich muss dich warnen: Vom Vorgänger-Projekt hab ich das Menü dringelassen - das ist hier im Snippet jetzt entfernt.
    Bei mir werden auch Menüs im Mainmodel zusammengebastelt - und das aus dem Vorgänger das hatte schon buttons zum Daten-Generieren und wieder löschen - war auch praktisch.
    Deine Tabbing-Konstruktion habich nicht nachgebaut.
    Soll ein anderer DelegateConverter ein anderes DG numerieren, so stell im MainModel eine andere Conversion bereit zum Anbinden an DelegateConverter.

    Auch deine Daten01_Klasse ist geschrumpft - aber den bescheuerten Namen hab ich dir gelassen. Entsprechend bescheuert sieht nun ja auch der Code im MainModel aus - also das könnte noch deutlich besser sein.

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Namespace Viewmodel
    3. Public Class Daten01_Klasse : Inherits NotifyPropertyChanged
    4. Private _wert01 As String
    5. Public Property Wert01() As String
    6. Get
    7. Return _wert01
    8. End Get
    9. Set(ByVal value As String)
    10. ChangePropIfDifferent(value, _wert01)
    11. End Set
    12. End Property
    13. Private _wert02 As String
    14. Public Property Wert02() As String
    15. Get
    16. Return _wert02
    17. End Get
    18. Set(ByVal value As String)
    19. ChangePropIfDifferent(value, _wert02)
    20. End Set
    21. End Property
    22. End Class
    23. End Namespace
    Ja, das wars schon, was zu coden war - alles andere Infrastruktur (Helperlein).

    Und CodeBehind hamwa nich
    Dateien

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

    Inzwischen gibt es eine "etwas" verbesserte Lösung. Div. Forenbeiträge überall zeigen, dass das Thema nicht nur mich interessiert.
    Daher hier die aktuelle Lösung.

    'Der Converter

    VB.NET-Quellcode

    1. Public Class ConvertItemToIndex
    2. Implements IValueConverter
    3. Public Function Convert(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.Convert
    4. Try
    5. 'Get the CollectionView from the DataGrid that is using the converter
    6. Dim Name_DataGrid As String = DirectCast(parameter, String)
    7. Dim DG As DataGrid = DirectCast(LogicalTreeHelper.FindLogicalNode(Application.Current.MainWindow, Name_DataGrid), DataGrid)
    8. Dim cv As CollectionView = DirectCast(DG.Items, CollectionView)
    9. 'Get the index of the item from the CollectionView
    10. Dim rowindex As Integer = cv.IndexOf(value) + 1
    11. Return rowindex.ToString()
    12. Catch e As Exception
    13. Throw New NotImplementedException(e.Message)
    14. End Try
    15. End Function
    16. Public Function ConvertBack(value As Object, targetType As System.Type, parameter As Object, culture As System.Globalization.CultureInfo) As Object Implements System.Windows.Data.IValueConverter.ConvertBack
    17. Throw New NotImplementedException()
    18. End Function
    19. End Class


    'und als Style im UserControl eingebunden

    XML-Quellcode

    1. <local:ConvertItemToIndex x:Key="Index"/>
    2. <Style TargetType="{x:Type DataGridRowHeader}">
    3. <Setter Property="Content" Value="{Binding Converter={StaticResource Index}, ConverterParameter=Aufnahmen_DataGrid}" />
    4. <Setter Property="Width" Value="35"/>
    5. </Style>


    Es ist mir endlich gelungen die ursprüngliche Suchmethode gegen ein passende auszutauschen. Statt "Findname" sucht jetzt der "LogicalTreeHelper.FindLogicalNode" nach dem DataGrid. Dieser arbeitet sich vom angegebenem Window bis in alle ChildElemente und macht nicht an einem "Namescope" halt, wie es Findname macht. (Ab dem UserControl wieder ein neuer NameScope)
    Der Name des zu suchenden DataGrids wird als ConverterParameter mitgegeben. So ist das Ganze auch wieder dynamisch und wiederverwendbar.
    kleiner Hinweis: Der Name des DataGrids muss im Projekt einmalig sein. Ansonsten wird das erste gefundene Control mit diesem Namen zurück geliefert.

    @ErfinderDesRades: Der Converter aus dem Links sieht auch recht kompliziert aus. Kam noch nicht dazu ihn zu testen. (mit Copy Paste ist das bestimmt nicht getan)
    Dein Beispielprojekt hab ich auch schon eine Weile studiert. Das ist ne Menge ziemlich komliziertes Zeug fürn Anfänger. Es wird noch eine ganze Weile dauern, bis klar ist, ob das zu meinem Projekt passt und ein Umbau auf diese Art mehr Sinn oder mehr Probleme macht. :)
    Werde mich aber noch weiter damit beschäftigen. Danke erst mal dafür.

    Gruß
    eddi