Hallo,
wie ich mittlerweile herausgefunden habe ist eine explizite Positionierung von Elementen innerhalb des UniformGrids nicht möglich. Deshalb geht unteres Beispiel schief:
<ItemsControl ItemsSource ="{Binding Path=Cells}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
Grid.Column="{Binding Cell.PositionX}"
Grid.Row="{Binding Cell.PositionY}"
Content="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid
Columns ="{Binding SizeX}"
Rows="{Binding SizeY}"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Kennt jemand eine clevere Lösung um die Elemente in einem Panel sortiert angezeigt zu bekommen? Die Source zu sortieren würde ich gern vermeiden.
Danke!
Um Rekursion zu verstehen, muss man erst mal Rekursion verstehen, muss man erst mal Rekursion verstehen, ....
Hallo wackelkontakt,
evtl. ist hier ein Canvas der passdenere Container.
evtl. ist hier ein Canvas der passdenere Container.
Und die Elemente dann per Koordinaten positionieren? Hmmm.... hört sich bißchen sehr kompliziert und fehleranfällig an. Ich glaube dann komm ich vielleicht doch besser die Source zu sortieren?! Oder gibt es vielleicht noch einen anderen Vorschlag?
Um Rekursion zu verstehen, muss man erst mal Rekursion verstehen, muss man erst mal Rekursion verstehen, ....
Und die Elemente dann per Koordinaten positionieren?
Hast du doch vor?
Oder wie genau willst du positionieren? Evtl. wäre da eine Skizze nicht schlecht.
Hallo winSharp,
ich glaube eine Skizze ist nicht nötig 😃 Ich habe einfach eine Art Schachbrett und möchte dort drin meine unsortierten Cell
-Elemente der Cells
-Collection anordnen. Dafür gibt es in Cell die Properties X- und Y-Position. Ich bräuchte irgendwie eine Mischung aus UniformGrid (eignet sich besonders gut für mein 'Schachbrett' + das Anlegen der Dimensionen geht einfach) und Grid um die Elemente an die richtigen Stellen zu plazieren.
Bei einem Canvas müßte ich ja über die Längenangaben meine Elemente plazieren oder?
Weißt du ungefähr was ich meine? (Gugg dir sonst auch noch mal mein Code-Beispiel an)
Viele Grüße
Um Rekursion zu verstehen, muss man erst mal Rekursion verstehen, muss man erst mal Rekursion verstehen, ....
Aha - also sozusagen ein UniformGrid, dass auch Leerzellen unterstützt, aber sonst auch gleich aufgebaut ist.
So was müsstest du wohl selbst schreiben - sollte nicht alzu komplex sein (von Panel ableiten und Measure sowie Arrange überschreiben).
Ausgehend von dem Zusatz in Wieso kann Grid nicht als ItemsPanel verwendet werden? habe ich mich nochmal mit der Thematik beschäftigt.
Die Lösung in dem verlinkten Blog, einfach einfach ein Grid als Basis zu nehmen, ist schon deutlich besser als mein damaliger Ansatz.
Eine Ableitung muss man jedoch nicht erstellen - zwei attached Properties reichen:
public static class Autogenerate
{
public static readonly DependencyProperty RowsProperty = DependencyProperty.RegisterAttached("Rows", typeof(int), typeof(Autogenerate), new UIPropertyMetadata(0, Rows_Changed));
public static readonly DependencyProperty ColumnsProperty = DependencyProperty.RegisterAttached("Columns", typeof(int), typeof(Autogenerate), new UIPropertyMetadata(0, Columns_Changed));
public static int GetRows(DependencyObject obj)
{
return (int) obj.GetValue(RowsProperty);
}
public static void SetRows(DependencyObject obj, int value)
{
obj.SetValue(RowsProperty, value);
}
public static int GetColumns(DependencyObject obj)
{
return (int) obj.GetValue(ColumnsProperty);
}
public static void SetColumns(DependencyObject obj, int value)
{
obj.SetValue(ColumnsProperty, value);
}
private static void Rows_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Grid grid = (Grid) d;
int rowsToAdd = ((int) e.NewValue) - grid.RowDefinitions.Count;
while (rowsToAdd < 0)
{
grid.RowDefinitions.RemoveAt(0);
rowsToAdd++;
}
while (rowsToAdd > 0)
{
grid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(1, GridUnitType.Star) });
rowsToAdd--;
}
}
private static void Columns_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Grid grid = (Grid) d;
int columnsToAdd = ((int) e.NewValue) - grid.ColumnDefinitions.Count;
while (columnsToAdd < 0)
{
grid.ColumnDefinitions.RemoveAt(0);
columnsToAdd++;
}
while (columnsToAdd > 0)
{
grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(1, GridUnitType.Star) });
columnsToAdd--;
}
}
}
Kleines, aber (wie ich finde 😁 ) nettes Beispielprojekt:
<Grid WpfApplication1:Autogenerate.Columns="{Binding Path=Columns}" WpfApplication1:Autogenerate.Rows="{Binding Path=Rows}">
<Button Grid.Column="1" Grid.Row="1" Content="Remove Row" Click="Remove_Row" />
<Button Grid.Column="0" Grid.Row="1" Content="Remove Colunm" Click="Remove_Column" />
<Button Grid.Column="1" Grid.Row="0" Content="Add Row" Click="Add_Row" />
<Button Grid.Column="0" Grid.Row="0" Content="Add Colunm" Click="Add_Column" />
</Grid>
public partial class MainWindow : Window
{
private readonly Foo _foo = new Foo();
public MainWindow()
{
InitializeComponent();
this.DataContext = this._foo;
}
private void Remove_Row(object sender, RoutedEventArgs e)
{
this._foo.Rows--;
}
private void Remove_Column(object sender, RoutedEventArgs e)
{
this._foo.Columns--;
}
private void Add_Row(object sender, RoutedEventArgs e)
{
this._foo.Rows++;
}
private void Add_Column(object sender, RoutedEventArgs e)
{
this._foo.Columns++;
}
}
public sealed class Foo
: INotifyPropertyChanged
{
private int _columns = 1;
private int _rows = 1;
public int Columns
{
get
{
return this._columns;
}
set
{
if (this.Columns == value)
return;
this._columns = value;
this.OnPropertyChanged("Columns");
}
}
public int Rows
{
get
{
return this._rows;
}
set
{
if (this.Rows == value)
return;
this._rows = value;
this.OnPropertyChanged("Rows");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(name));
}
}