Hallo!
Ich möchte eine Matrix (Zeilen und Spalten) welche in einem Objekt-Typ (AblageTyp) definiert sind grafisch darstellen.
Der AblageTyp hat die (integer) Eigenschaften MatrixZeilen und MatrixSpalten.
public partial class AblageTyp
{
/// <summary>
/// ID des Ablage-Typ's.
/// </summary>
public long ID { get; set; } = DateTime.Now.Ticks;
...
/// <summary>
/// Anzahl der Spalten des Ablage-Typ's
/// </summary>
public int MatrixSpalten { get; set; } = 2;
/// <summary>
/// Anzahl der Zeilen des Ablage-Typ's
/// </summary>
public int MatrixZeilen { get; set; } = 3;
...
}
Im ViewModel habe ich eine View einer AblageTyp'en-Liste.
class VMAblageTypenVerwaltung : MVVM_Base
{
internal CollectionViewSource CVSAblageTypen { get; set; } = new CollectionViewSource(); // CVS deklarieren
/// <summary>
/// View der Ablage-Typen Liste.
/// </summary>
public ICollectionView AblageTypenListeView { get => CVSAblageTypen.View; }
...
Diese Daten-View zeige ich in einem ListView an.
<ListView ItemsSource="{Binding AblageTypenListeView}" IsSynchronizedWithCurrentItem="True">
<i:Interaction.Behaviors>
<local:AblageTypChangeBehavior/>
</i:Interaction.Behaviors>
<ListView.View>
<GridView>
<GridViewColumn DisplayMemberBinding="{Binding Path=Bezeichnung}" Header="Bezeichnung" />
<GridViewColumn DisplayMemberBinding="{Binding Path=Kapazität}" Header="Kapazität" />
<GridViewColumn DisplayMemberBinding="{Binding Path=MatrixZeilen}" Header="Matrix-Zeilen" />
<GridViewColumn DisplayMemberBinding="{Binding Path=MatrixSpalten}" Header="Matrix-Spalten" />
</GridView>
</ListView.View>
</ListView>
Beim navigieren des Benutzers durch die AblageTyp'en wird über einen Behavior eine Methode (RefreshAblageTypMatrixListe) aufgerufen die im ViewModel eine zentrale Matrix-Liste (AblageTypMatrixListe) in welcher Border entsprechend der Summe der aktuellen Matrix dynamisch gefüllt werden, aktualisiert.
public void RefreshAblageTypMatrixListe(AblageTyp aktAblageTyp)
{
AblageTypMatrixListe.Clear(); // Matrix-Liste leeren
for (int i = 0; i < aktAblageTyp.MatrixZeilen * aktAblageTyp.MatrixSpalten; i++) // Matrix iterieren
{
Border border = new();
border.Margin = new(5); border.Background = Brushes.Blue;
border.MinHeight = 20; border.MinWidth = 20;
AblageTypMatrixListe.Add(border);
}
OnChanged(nameof(AblageTypMatrixListe)); // View der Matrix-Liste aktualisieren
}
Entsprechend dem Ablage-Typ besteht die Matrix-Liste aus einer unterschiedlichen Anzahl an Bordern.
Diese (in der passenden Matrix) möchte ich grafisch darstellen. Dazu verwende ich ein ItemControl dem ich als ItemsSource die dynamisch gefüllte Matrix-Liste zuordne.
<ItemsControl ItemsSource="{Binding AblageTypMatrixListe, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Height="200" Width="200" Rows="3" Columns="3" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Beim ersten Aufruf wird die Anzahl an Border auch angezeigt (siehe Bild). Bei einem Wechsel des Ablage-Art Eintrages wird zwar die ViewModel Matrix-Liste korrekt aktualisiert aber die grafische Anordnung ändert sich nicht.
Es ergeben sich für mich 2 Fragen:
Hallo!
Ein Teil der Fragen hat sich geklärt.
Die Aktualisierung der Anzeige des ItemsControl wird ausgeführt, wenn ich für die zentrale AblageTypMatrixListe eine OC verwende.
private ObservableCollection<Border> _AblageTypMatrixListe;
/// <summary>
/// Liste der Ablage-Typ Matrix Einträge
/// </summary>
public ObservableCollection<Border> AblageTypMatrixListe { get => _AblageTypMatrixListe; set { _AblageTypMatrixListe = value; OnChanged(nameof(AblageTypMatrixListe)); } }
Bei einer OC wird die View ja automatisch auch beim Verändern des Inhalts (hinzufügen/löschen...) aktualisiert aber ich war davon ausgegangen, dass die manuelle Aktualisierung der View in der Befüllungs-Methode (RefreshAblageTypMatrixListe) reicht, aber ... ?
public void RefreshAblageTypMatrixListe(AblageTyp aktAblageTyp)
{
....
OnChanged(nameof(AblageTypMatrixListe)); // View der Matrix-Liste aktualisieren
}
Nun muss ich nur noch die Matrix gebunden bekommen. Dann wärs perfekt.
So, geschafft!
Ich habe dem ViewModel noch zwei Eigenschaften (MatrixZeilen und MatrixSpalten) hinzugefügt, dem (beim Wechsel des Ablage-Typs) die Matrix-Werte des aktuellen Ablage-Typs zugeordnet werden:
public void RefreshAblageTypMatrixListe(AblageTyp aktAblageTyp)
{
MatrixZeilen = aktAblageTyp.MatrixZeilen;
MatrixSpalten = aktAblageTyp.MatrixSpalten;
...
}
und diese Werte im ItemsPanelTemplate an die zugeordneten Eigenschaften (Rows und Columns) des UniformGrid's gebunden.
<ItemsControl ItemsSource="{Binding AblageTypMatrixListe, UpdateSourceTrigger=PropertyChanged}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Height="200" Width="200"
Rows="{Binding MatrixZeilen, UpdateSourceTrigger=PropertyChanged}"
Columns="{Binding MatrixSpalten, UpdateSourceTrigger=PropertyChanged}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Jetzt wird die Matrix beim Ändern des Ablage-Typ's korrekt aktualisiert.