Skip to content

Instantly share code, notes, and snippets.

@GABowers
Created November 9, 2024 15:32
Show Gist options
  • Save GABowers/9d14a8d02008d80e1ae18c5eac719044 to your computer and use it in GitHub Desktop.
Save GABowers/9d14a8d02008d80e1ae18c5eac719044 to your computer and use it in GitHub Desktop.
A WPF grid with resizable rows, where resizing a row does not change the size of other rows.
// derived from https://stackoverflow.com/a/26540204
public class BindableGrid : Grid
{
bool spacingRow = false;
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(BindableGrid), new FrameworkPropertyMetadata(null, OnItemsSourceChanged));
public static readonly DependencyProperty ItemTemplateProperty = DependencyProperty.Register("ItemTemplate", typeof(DataTemplate), typeof(BindableGrid), new FrameworkPropertyMetadata(null, OnItemTemplateChanged));
public IEnumerable ItemsSource
{
get { return (IEnumerable)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public DataTemplate ItemTemplate
{
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
}
public static void OnItemsSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((BindableGrid)d).OnItemsSourceChanged((IEnumerable)e.OldValue, (IEnumerable)e.NewValue);
}
public void OnItemsSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
INotifyCollectionChanged oldValueNotify;
if ((oldValueNotify = oldValue as INotifyCollectionChanged) != null)
{
oldValueNotify.CollectionChanged -= ItemsSourceCollectionChanged;
}
INotifyCollectionChanged newValueNotify;
if ((newValueNotify = newValue as INotifyCollectionChanged) != null)
{
newValueNotify.CollectionChanged += ItemsSourceCollectionChanged;
}
}
public static void OnItemTemplateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((BindableGrid)d).OnItemTemplateChanged((DataTemplate)e.OldValue, (DataTemplate)e.NewValue);
}
public void OnItemTemplateChanged(DataTemplate oldItemTemplate, DataTemplate newItemTemplate)
{
}
private void ItemsSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Reset)
{
RowDefinitions.Clear();
Children.Clear();
}
else if (e.Action == NotifyCollectionChangedAction.Add)
{
AddItems(e.NewItems);
}
else
{
throw new InvalidOperationException(string.Format("Action '{0}' is not valid.", e.Action));
}
}
private void AddItems(IList items)
{
if(!spacingRow)
{
spacingRow = true;
RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1, GridUnitType.Star),
});
}
foreach (var item in items)
{
RowDefinitions.Insert(Children.Count, new RowDefinition
{
Height = new GridLength(100, GridUnitType.Pixel),
MinHeight = 40,
});
var contentPresenter = new ContentPresenter();
contentPresenter.SetValue(ContentPresenter.ContentTemplateProperty, ItemTemplate);
contentPresenter.Content = item;
SetRow(contentPresenter, Children.Count);
Children.Add(contentPresenter);
RowDefinitions.Insert(Children.Count, new RowDefinition { Height = GridLength.Auto });
var gridSplitter = new GridSplitter
{
Height = 2,
Background = new SolidColorBrush(Color.FromArgb(127, 127, 127, 127)),
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Stretch,
};
SetRow(gridSplitter, Children.Count);
Children.Add(gridSplitter);
}
}
}
@GABowers
Copy link
Author

GABowers commented Nov 9, 2024

Usage:

<localViews:BindableGrid ItemsSource="{Binding ItemsList}">
    <localViews:BindableGrid.ItemTemplate>
        <DataTemplate>
            <Control/>
        </DataTemplate>
    </localViews:BindableGrid.ItemTemplate>
</localViews:BindableGrid>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment