Hallo myCSharp Community,
ich befinde mich noch auf den ersten Schritten zur Erlernung von c# und WPF, wo mir sicherlich noch einige Grundlagen fehlen. Dennoch habe ich bereits ein konkretes Problem, an dem ich bereits seit Tagen hadere.
Ich möchte in einer UI meine ObservableCollection "ObservableAxis" mit verschiedenen Canvases darstellen. Da die Werte der Bestandteile und UI mal dynamisch sein sollen, verwende ich die ObservableCollection.
Grundlage ist die o.g. ObservableAxis, die sich wie folgt aufbaut:
public partial class MainWindow : Window
{
public static ObservableCollection<Axis> ObservableAxis = new ObservableCollection<Axis>();
public MainWindow()
{
InitializeComponent();
Axis Axis0 = new Axis(0);
Axis0.MySegments.Add(new Segment(0, 10, 100, Axis0.Axis_Number));
Axis0.MySegments.Add(new Segment(1, 20, 200, Axis0.Axis_Number));
Axis Axis1 = new Axis(1);
Axis1.MySegments.Add(new Segment(0, 50, 500, Axis1.Axis_Number));
Axis1.MySegments.Add(new Segment(1, 60, 600, Axis1.Axis_Number));
ObservableAxis.Add(Axis0);
ObservableAxis.Add(Axis1);
ItemsControl_Axis.ItemsSource = ObservableAxis;
}
}
Jede Axis besteht widerum aus mehreren Segmenten, mit verschiedenen Eigenschaften
public class Axis
{
public ObservableCollection<Segment> MySegments;
public int Axis_Number { get; set; }
public Axis(int axis_number)
{
Axis_Number = axis_number;
MySegments = new ObservableCollection<Segment>();
}
}
public class Segment
{
public int Counter_Seg { get; set; }
public double Start { get; set; }
public double Duration { get; set; }
public int Axis_Counter { get; set; }
public string ID { get; set; }
public Segment(int counter_seg, double start, double duration, int axis_counter)
{
Counter_Seg = counter_seg;
Start = start;
Duration = duration;
Axis_Counter = axis_counter;
}
}
Jede Axis soll durch einen grünen Canvas über die gesamte Breite dargestellt werden (StackPanel vertical) und innerhalb einer jeden Axis sollen die zugeordneten Segmente als gelbe Canvases **horizontal **erfolgen.
Bisher habe ich folgendes Bild erreicht --> siehe Bild im Anhang oben
Im unteren Teil des Bildes ist das Ziel angedeutet, welches ich verfolge.
Im XAML habe ich bereits folgendes umgesetzt:
<Window x:Class="WpfApp2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<HierarchicalDataTemplate x:Key="myLevel1Template" DataType="{x:Type local:Axis}" ItemsSource="{Binding Path=MySegments}">
<Border BorderBrush="Black" BorderThickness="1">
<Canvas Width="750" Height="50" Background="DarkSeaGreen"/>
</Border>
</HierarchicalDataTemplate>
<Style x:Key="Canvas" TargetType="Canvas">
<Setter Property="Canvas.Left" Value="{Binding Start}"/>
<Setter Property="Canvas.Top" Value="5"/>
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Height" Value="40"/>
<Setter Property="Width" Value="{Binding Duration}"/>
</Style>
</Window.Resources>
<Grid>
<Canvas Background="NavajoWhite">
<ItemsControl x:Name="ItemsControl_Axis"
ItemTemplate="{StaticResource myLevel1Template}">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:Segment}">
<Canvas Style="{StaticResource Canvas}">
<Label Content="{Binding Path=Axis_Counter}" Canvas.Left="10" Canvas.Top="10"/>
</Canvas>
</DataTemplate>
</ItemsControl.Resources>
</ItemsControl>
</Canvas>
</Grid>
</Window>
Schon mal Danke für eure Hilfe und Gruß
Phil
Wo genau liegt das Problem? Was funktioniert nicht? Was hast du schon probiert?
Schau mal in [Hinweis] Wie poste ich richtig?, du mußt uns schon ein paar mehr Infos geben, um dir helfen zu können.
Schau auch mal in [Artikel] MVVM und DataBinding, besonders in den Abschnitt Debugging, um deine DataBindings debuggen zu können.
Weeks of programming can save you hours of planning
Sry für die nicht ausführliche Beschreibung des Problems.
Ich bekomme es nicht hin, dass mir wie auf dem Screenshot (unterer Abschnitt) die zweite Ebene meiner OberserveableCollection dargestellt wird. Ich schaffe es nur die erste Ebene zu visualisieren.
Auch wenn ich nur die blanken Zahlenwerte darstellen möchte, sagen wir "axis_number" auf der ersten Ebene und "Segment.Start" aus der zweiten Ebene wird mir partout nur die erste Ebene angezeigt.
Durch Ändern der Art der Darstellung (<-- hier fehlt mir der richtige Begriff) von
<ItemsControl ItemsSource= ...>
...
</ItemsControl>
in einen TreeView
<TreeView ItemsSource= ...>
...
</TreeView>
ist es möglich, dass mir auch die zweite Ebene angezeigt wird. --> siehe Anhang. Ziel ist es jedoch, dass die gelben Canvas innerhalb der grünen sein sollen.
Ist es überhaupt möglich mit einem ItemsControl oder ListBox die verschiedenen Ebenen einer ObservableCollection darzustellen oder muss man sobald es mehr als eine Schicht hat auf einen TreeView zurückgreifen? Wenn es möglich ist wie?
Danke
Ich denke, du brauchst einfach 2 ineinander verschachtelte ItemsControl
. Also baue statt dem HierarchicalDataTemplate
daraus ein ItemsControl
(mit entsprechender Anpassung des DataTemplate
).
Edit: Für das innere ItemsControl
benötigst du dann noch die horizontale Ausrichtung, s. z.B. ItemsControl with horizontal orientation.
Außerdem könnte noch How to position controls using Canvas control in WPF using MVVM für dich interessant sein (da du ja freie Positionierung der Canvas willst).
Danke für die Hinweise, werde ich ausprobieren, sobald ich wieder da bin und die Antwort posten
Hi,
nach längerer Stille habe ich mittlerweile folgenden Fortschritt, der mir das beigefügte Bild darstellt (oben links).
Noch nicht ganz das Ergebnis was ich erreichen möchte (Bild unten rechts) und daher meine Nachfrage wo mein Denkfehler ist. Das kleine gelbe Rechteck sollte eigentlich in der selben Reihe/Höhe sein wie das direkt oben drüber.
Ich habe es nach dem Vorschlag der verschachtelten ItemsControl mit horizontaler Ausrichtung probiert, aber klappt noch nicht ganz.
<TreeView x:Name="trv">
<TreeView.Resources>
<HierarchicalDataTemplate ItemsSource="{Binding MySegments}" DataType="{x:Type local:Axis}">
<TextBlock Text="{Binding Path=Axis_Number}"/>
</HierarchicalDataTemplate>
<DataTemplate DataType="{x:Type local:Segment}">
<ItemsControl >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="800" Height="50" Background="DarkSeaGreen"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl ItemsSource="{Binding}" Canvas.Left="{Binding Path=Start}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<Canvas Width="{Binding Path=Duration}" Background="Yellow" Height="50"/>
</ItemsControl>
</ItemsControl>
</DataTemplate>
</TreeView.Resources>
</TreeView>
</Window>
Und die zugrundeliegende ObservableCollection:
ObservableAxis = new ObservableCollection<Axis>();
Axis Axis0 = new Axis(0);
Axis0.MySegments.Add(new Segment(10, 100));
Axis0.MySegments.Add(new Segment(200, 30));
Axis Axis1 = new Axis(1);
Axis1.MySegments.Add(new Segment(50, 500));
ObservableAxis.Add(Axis0);
ObservableAxis.Add(Axis1);
trv.ItemsSource = ObservableAxis;
Danke für eure Hilfe und Gruß
Phil