Moin zusammen,
ich sitze seit letzter Woche leider wieder einmal an einem Problem. Ich möchte in einer bestehenden WinForms Anwendung, die auf Basis einer Datenbank funktioniert eine TabPage zum ausfüllen einer Checkliste hinzufügen. Die Chekcliste wurde bislang händisch auf Papier ausgefüllt und soll nun ebenfalls in der Datenbank gespeichert werden. Um die Checklisten optisch möglichst gleich zu halten, habe ich mich dazu entschlossen dafür WPF Controls zu erstellen, da ich persönlich die Umsetzung in WPF leichter fand, und diese dann innerhalb eines ElementHosts ElementHost_CHECKLISTS auf der entschprechenden TabPage zu hosten.
Links neben der eigentlichen Checkliste befindet sich eine ListBox, mit deren Hilfe der User eine Checkliste selektieren kann, die dann rechts danebene angezeigt werden soll (vgl. ChecklistControl.jpeg)
Für jede Checkliste gibt es im oberen Teil einen Bereich, der vom Aufbau immer gleich ist. Anschließend folgt ein dynamisch erzeugter Bereich, der je nach Checkliste unterschiedlich lang ist. Konkret heßt das, nach dem fixen Teil befindet sich ein StackPanel, zu dem dynamisch weitere Controls (DepartmentControls) hinzugefügt werden.
In jeder Zeile diese DepartmentControls gibt es Kategorien, zu der der User eine Auswahl treffen soll. Das wird über RadioButtons und entsprechenden RadioButtonGroups realisiert. Am Ende werden die Werte dann in die Datenbank geschrieben. Beim erneuten Laden der Listen passiert nun aber Folgendes:
ChecklistControl.xaml:
Dann die zu diesem StackPanel hinzugefügten DeparmentControls, nur beispielhaft die erste Zeile:
Laden der Daten aus der Datenbank und erzeugen der ChecklistControls:
Ich erzeuge für jede Dapertment ein neues DepartmentControl innerhalb einer For Each Schleife und füge es am Ende von jedem Durchgang dem StackPanel_Deparmentes des ChecklistControls hinzu. Meine erste Vermutung war nun, dass im nächsten Druchgang mit Dim rating As New DepartmentControl ich auch das Objekt im StackPanel neu erzeuge und dardurch alles überschrieben wird. Kann aber nicht sein, denn die Kommentare und ID's in den TextBlocks der einzenlnen DepartmentControls werden ja nicht überschrieben, sondern werden richtig zugeordnet. Wenn ich das Ganze debugge und die IsChecked Eigenschaften eines DepartmentControls überwache, stimmt zunächst alles, auch nach dem Hinzufügen zum StackPanel und nach dem Erzeugen des nächsten DepartmenControls. Erst beim Zuweisen der Werte für das nächste DepartmentControl werden die IsChecked Eigenschaften des vorherigen DepartmentControls alle auf False gesetzt.
Grundsätzlich erfolgt innerhalb des DeparmentControls das setzten der IsChecked Eigenschaften der RadioButtons:
Es gibt Properties vom Typ Short um die Ratings der Kategorien zu speichern. Die passenden RadioButtons werden dann anhand des Namens identifiziert. Zum Beispiel: Wert für Kategorie 1 ist -3. Dann wird der RadioButton "RB_Cat1_M3".IsChecked = True gesetzt. Da sich der Name aus einem dynamisch erzeugten String zusammensetzt, spreche ich den RadioButton über Me.FindName(...) an.
Was kann ich also tun, damit die IsChecked Eigenschaften nicht überschrieben werden, sondern genauso wie der Text der TextBlocks bestehen beleiben?
Viel Grüße
Andreas
ich sitze seit letzter Woche leider wieder einmal an einem Problem. Ich möchte in einer bestehenden WinForms Anwendung, die auf Basis einer Datenbank funktioniert eine TabPage zum ausfüllen einer Checkliste hinzufügen. Die Chekcliste wurde bislang händisch auf Papier ausgefüllt und soll nun ebenfalls in der Datenbank gespeichert werden. Um die Checklisten optisch möglichst gleich zu halten, habe ich mich dazu entschlossen dafür WPF Controls zu erstellen, da ich persönlich die Umsetzung in WPF leichter fand, und diese dann innerhalb eines ElementHosts ElementHost_CHECKLISTS auf der entschprechenden TabPage zu hosten.
Links neben der eigentlichen Checkliste befindet sich eine ListBox, mit deren Hilfe der User eine Checkliste selektieren kann, die dann rechts danebene angezeigt werden soll (vgl. ChecklistControl.jpeg)
Für jede Checkliste gibt es im oberen Teil einen Bereich, der vom Aufbau immer gleich ist. Anschließend folgt ein dynamisch erzeugter Bereich, der je nach Checkliste unterschiedlich lang ist. Konkret heßt das, nach dem fixen Teil befindet sich ein StackPanel, zu dem dynamisch weitere Controls (DepartmentControls) hinzugefügt werden.
In jeder Zeile diese DepartmentControls gibt es Kategorien, zu der der User eine Auswahl treffen soll. Das wird über RadioButtons und entsprechenden RadioButtonGroups realisiert. Am Ende werden die Werte dann in die Datenbank geschrieben. Beim erneuten Laden der Listen passiert nun aber Folgendes:
- Die dynamisch erzeugten DepartmentControls werden geladen und richtig dem StackPanel der ChecklistControl hinzugefügt
- Die Kommentare in der "Additional comments" Spalte ganz rechts werden richtig geladen und richtig zugeordnet.
- ABER: Die User Auswahl der RadioButtons wird nur für das letzte hinzugefügte DepartmentControl geladen. Alle zuvor hinzugefügten beinhalten absolut keine Auswahl.
ChecklistControl.xaml:
Dann die zu diesem StackPanel hinzugefügten DeparmentControls, nur beispielhaft die erste Zeile:
XML-Quellcode
- <UserControl x:Class="CornerChecklistControl"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:local="clr-namespace:RMG_Tracknote"
- mc:Ignorable="d"
- d:DesignHeight="200" d:DesignWidth="1149" Height="104"
- Background="White"
- FontSize="9pt" FontFamily="Segeo UI" Margin="0,-1,0,-1" HorizontalAlignment="Stretch">
- <Border BorderBrush="Black" BorderThickness="2,1,2,2" Height="104">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="20"/>
- <RowDefinition Height="20"/>
- <RowDefinition Height="20"/>
- <RowDefinition Height="20"/>
- <RowDefinition Height="20"/>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="50"/>
- <ColumnDefinition Width="70"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="26"/>
- <ColumnDefinition Width="*"/>
- </Grid.ColumnDefinitions>
- <Border Grid.Column="0" Grid.Row="0" Grid.RowSpan="5" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,-1">
- <TextBlock x:Name="TB_Department" Text="#" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="12pt" FontWeight="Bold"/>
- </Border>
- <Border Grid.Column="13" Grid.Row="0" Grid.RowSpan="5" BorderBrush="Black" BorderThickness="1" Margin="0,-1,-1,-1">
- <TextBox x:Name="TB_Comments" Text="Comments" TextAlignment="Left" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="10,5" BorderThickness="0"/>
- </Border>
- <Border Grid.Column="2" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0">
- <RadioButton x:Name="RB_Cat1_M5" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- <Border Grid.Column="3" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0">
- <RadioButton x:Name="RB_Cat1_M4" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- <Border Grid.Column="4" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0">
- <RadioButton x:Name="RB_Cat1_M3" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- <Border Grid.Column="5" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0">
- <RadioButton x:Name="RB_Cat1_M2" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- <Border Grid.Column="6" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0">
- <RadioButton x:Name="RB_Cat1_M1" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- <Border Grid.Column="7" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0" Background="LightGray">
- <RadioButton x:Name="RB_Cat1_N" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- <Border Grid.Column="8" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0">
- <RadioButton x:Name="RB_Cat1_1" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- <Border Grid.Column="9" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0">
- <RadioButton x:Name="RB_Cat1_2" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- <Border Grid.Column="10" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0">
- <RadioButton x:Name="RB_Cat1_3" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- <Border Grid.Column="11" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0">
- <RadioButton x:Name="RB_Cat1_4" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- <Border Grid.Column="12" Grid.Row="0" BorderBrush="Black" BorderThickness="1" Margin="-1,-1,0,0">
- <RadioButton x:Name="RB_Cat1_5" VerticalAlignment="Center" HorizontalAlignment="Center" GroupName="Brakelock"/>
- </Border>
- ...
- </Grid>
- </Border>
- </UserControl>
Laden der Daten aus der Datenbank und erzeugen der ChecklistControls:
VB.NET-Quellcode
- Private Sub LoadChecklists()
- ListBox_CHECKLISTS.Items.Clear()
- Dim checklists As Data.DataTable = query_DataTable("SELECT ...")
- If checklists IsNot Nothing Then
- For Each list As DataRow In checklists.Rows
- Dim checklist As New ChecklistControl
- With checklist
- .EventName = evname
- .SessionName = list("stypename").ToString()
- .ListName = list("stypename").ToString() & " " & list("checklist_type").ToString()
- .Conditions = list("conditions").ToString()
- ....
- 'Fill general comment TextBlocks
- For i As Integer = 1 To 4
- If list("mlf_" & i).ToString() IsNot String.Empty And list("mlf_" & i).ToString() <> "0" Then
- .LimitingFactors(i - 1) = (list("mlf_" & i).ToString())
- End If
- If list("msf_" & i).ToString() IsNot String.Empty And list("msf_" & i).ToString() <> "0" Then
- .StrongFactors(i - 1) = (list("msf_" & i).ToString())
- End If
- Next
- End With
- Dim departments As Data.DataTable = query_DataTable("SELECT * FROM ...")
- If departments IsNot Nothing Then
- For Each department As DataRow In departments .Rows
- Dim rating As New DepartmentControl()
- With rating
- .DepartmentID = department("corner_no").ToString() 'Nach diesem Schritt stimmt die Auswahl des vorherigen DepartmentControls nicht mehr und alles ist IsChecked = False
- .Cat1= CShort(department("Cat1"))
- ...
- .Comment = department("comment").ToString()
- End With
- checklist.StackPanel_Departments.Children.Add(rating)
- Next
- End If
- ListBox_CHECKLISTS.Items.Add(checklist)
- Next
- End If
- End Sub
- Private Sub ListBox_CHECKLISTS_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LB_CHECKLISTS.SelectedIndexChanged
- If ListBox_CHECKLISTS.SelectedItem IsNot Nothing Then
- Dim checklist As ChecklistControl = TryCast(ListBox_CHECKLISTS.SelectedItem, ChecklistControl)
- Me.ElementHost_CHECKLIST.Child = checklist
- End If
- End Sub
Ich erzeuge für jede Dapertment ein neues DepartmentControl innerhalb einer For Each Schleife und füge es am Ende von jedem Durchgang dem StackPanel_Deparmentes des ChecklistControls hinzu. Meine erste Vermutung war nun, dass im nächsten Druchgang mit Dim rating As New DepartmentControl ich auch das Objekt im StackPanel neu erzeuge und dardurch alles überschrieben wird. Kann aber nicht sein, denn die Kommentare und ID's in den TextBlocks der einzenlnen DepartmentControls werden ja nicht überschrieben, sondern werden richtig zugeordnet. Wenn ich das Ganze debugge und die IsChecked Eigenschaften eines DepartmentControls überwache, stimmt zunächst alles, auch nach dem Hinzufügen zum StackPanel und nach dem Erzeugen des nächsten DepartmenControls. Erst beim Zuweisen der Werte für das nächste DepartmentControl werden die IsChecked Eigenschaften des vorherigen DepartmentControls alle auf False gesetzt.
Grundsätzlich erfolgt innerhalb des DeparmentControls das setzten der IsChecked Eigenschaften der RadioButtons:
VB.NET-Quellcode
- Public Sub SetSelection(value As Short, propertyName As String)
- If value >= 1 And value <= 5 Then
- Dim obj As System.Windows.Controls.RadioButton = TryCast(Me.FindName("RB_" & propertyName & "_" & value.ToString()), System.Windows.Controls.RadioButton)
- obj.IsChecked = True
- End If
- If value >= -5 And value <= -1 Then
- Dim obj As System.Windows.Controls.RadioButton = TryCast(Me.FindName("RB_" & propertyName & "_M" & (-1 * value).ToString()), System.Windows.Controls.RadioButton)
- obj.IsChecked = True
- End If
- If value = 0 Then
- Dim obj As System.Windows.Controls.RadioButton = TryCast(Me.FindName("RB_" & propertyName & "_N"), System.Windows.Controls.RadioButton)
- obj.IsChecked = True
- End If
- End Sub
Es gibt Properties vom Typ Short um die Ratings der Kategorien zu speichern. Die passenden RadioButtons werden dann anhand des Namens identifiziert. Zum Beispiel: Wert für Kategorie 1 ist -3. Dann wird der RadioButton "RB_Cat1_M3".IsChecked = True gesetzt. Da sich der Name aus einem dynamisch erzeugten String zusammensetzt, spreche ich den RadioButton über Me.FindName(...) an.
Was kann ich also tun, damit die IsChecked Eigenschaften nicht überschrieben werden, sondern genauso wie der Text der TextBlocks bestehen beleiben?
Viel Grüße
Andreas