Skip to content

Commit dc90836

Browse files
committed
Fixes #791
1 parent 06b01b3 commit dc90836

9 files changed

+367
-637
lines changed

Changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
- [#786](../../issues/786) - InRibbonGallery: Dynamic ItemWidth / use translated Text in items
66
- [#788](../../issues/788) - Maximize icon is incorrectly drawn on high-dpi displays
77
- [#789](../../issues/789) - Opening gallery messes up InRibbonGallery resizing.
8+
- [#791](../../issues/791) - Problem with dynamic items in InRibbonGallery
89

910
## 7.1.0
1011
- ### Bug fixes
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,16 @@
11
// ReSharper disable once CheckNamespace
22
namespace Fluent
33
{
4-
using System;
5-
using System.Diagnostics;
64
using System.Windows;
75
using System.Windows.Controls;
86
using System.Windows.Media;
9-
using Fluent.Extensions;
10-
using Fluent.Internal;
117
using Fluent.Internal.KnownBoxes;
128

139
/// <summary>
1410
/// Represents container of grouped gallery items in GalleryPanel or Gallery
1511
/// </summary>
1612
public class GalleryGroupContainer : HeaderedItemsControl
1713
{
18-
#region Fields
19-
20-
private int previousItemsCount;
21-
22-
// Whether MinWidth/MaxWidth of the ItemsPanel needs to be updated
23-
private bool minMaxWidthNeedsToBeUpdated = true;
24-
private Panel itemsPanel;
25-
private FrameworkElement targetForSizeConstraints;
26-
27-
#endregion
28-
2914
#region Properites
3015

3116
#region IsHeadered
@@ -127,12 +112,7 @@ public int MinItemsInRow
127112
/// </summary>
128113
public static readonly DependencyProperty MinItemsInRowProperty =
129114
DependencyProperty.Register(nameof(MinItemsInRow), typeof(int),
130-
typeof(GalleryGroupContainer), new FrameworkPropertyMetadata(IntBoxes.Zero, FrameworkPropertyMetadataOptions.AffectsMeasure, OnMinItemsInRowChanged));
131-
132-
private static void OnMinItemsInRowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
133-
{
134-
OnMaxOrMinItemsInRowChanged(d, e);
135-
}
115+
typeof(GalleryGroupContainer), new FrameworkPropertyMetadata(IntBoxes.Zero, FrameworkPropertyMetadataOptions.AffectsMeasure));
136116

137117
#endregion
138118

@@ -150,35 +130,14 @@ public int MaxItemsInRow
150130
/// <summary>
151131
/// <see cref="DependencyProperty"/> for <see cref="MaxItemsInRow"/>.
152132
/// </summary>
153-
public static readonly DependencyProperty MaxItemsInRowProperty = DependencyProperty.Register(nameof(MaxItemsInRow), typeof(int), typeof(GalleryGroupContainer), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsMeasure, OnMaxItemsInRowChanged));
154-
155-
private static void OnMaxItemsInRowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
156-
{
157-
OnMaxOrMinItemsInRowChanged(d, e);
158-
}
133+
public static readonly DependencyProperty MaxItemsInRowProperty = DependencyProperty.Register(nameof(MaxItemsInRow), typeof(int), typeof(GalleryGroupContainer), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsMeasure));
159134

160135
#endregion
161136

162-
private Panel RealItemsPanel => this.itemsPanel ?? (this.itemsPanel = FindItemsPanel(this));
163-
164-
private static void OnMaxOrMinItemsInRowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
165-
{
166-
var galleryGroupContainer = (GalleryGroupContainer)d;
167-
galleryGroupContainer.minMaxWidthNeedsToBeUpdated = true;
168-
}
169-
170137
#endregion
171138

172139
#region Initialization
173140

174-
/// <summary>
175-
/// Creates a new instance of <see cref="GalleryGroupContainer"/>.
176-
/// </summary>
177-
public GalleryGroupContainer()
178-
{
179-
this.Unloaded += this.HandleUnloaded;
180-
}
181-
182141
/// <summary>
183142
/// Static constructor
184143
/// </summary>
@@ -192,163 +151,9 @@ protected override void OnItemsPanelChanged(ItemsPanelTemplate oldItemsPanel, It
192151
{
193152
base.OnItemsPanelChanged(oldItemsPanel, newItemsPanel);
194153

195-
this.itemsPanel = null;
196-
this.minMaxWidthNeedsToBeUpdated = true;
197-
this.InvalidateMeasure();
198-
}
199-
200-
#endregion
201-
202-
#region MaxWidth Updating
203-
204-
// Sets MaxWidth of the items panel based of ItemsInRow property
205-
private void UpdateMinAndMaxWidth(Size constraint)
206-
{
207-
if (this.minMaxWidthNeedsToBeUpdated == false)
208-
{
209-
return;
210-
}
211-
212-
if (this.RealItemsPanel == null)
213-
{
214-
// Item's panel is not ready now
215-
if (this.IsLoaded)
216-
{
217-
Debug.WriteLine("Panel with IsItemsHost = true is not found in GalleryGroupContainer (probably the style is not correct or haven't attached yet)");
218-
}
219-
else
220-
{
221-
// Prevent duplicate registration
222-
this.Loaded -= this.HandleLoaded;
223-
this.Loaded += this.HandleLoaded;
224-
}
225-
226-
return;
227-
}
228-
229-
this.minMaxWidthNeedsToBeUpdated = false;
230-
231-
// Issue references:
232-
// - #542 + commit https://github.com/fluentribbon/Fluent.Ribbon/commit/8b458b1cfc5e440f54778c808142fffa67a23978
233-
// - #666
234-
// We need to check if we are inside a closed InRibbonGallery.
235-
// - If we are inside an closed InRibbonGallery we need to restrict the size of "this"
236-
// - If we are inside an opened InRibbonGallery or not inside an InRibbonGallery we need to restrict the size of "RealItemsPanel"
237-
var inRibbonGallery = UIHelper.GetParent<InRibbonGallery>(this);
238-
var isInsideClosedInRibbonGallery = inRibbonGallery != null && inRibbonGallery.IsDropDownOpen == false;
239-
this.targetForSizeConstraints = isInsideClosedInRibbonGallery ? (FrameworkElement)this : this.RealItemsPanel;
240-
241-
var nonTargetForSizeConstraints = isInsideClosedInRibbonGallery ? (FrameworkElement)this.RealItemsPanel : this;
242-
243-
nonTargetForSizeConstraints.MinWidth = 0;
244-
nonTargetForSizeConstraints.MaxWidth = double.PositiveInfinity;
245-
246-
if (this.Orientation == Orientation.Vertical)
247-
{
248-
// Min/Max is used for Horizontal layout only
249-
this.targetForSizeConstraints.MinWidth = 0;
250-
this.targetForSizeConstraints.MaxWidth = double.PositiveInfinity;
251-
return;
252-
}
253-
254-
var itemWidth = this.GetItemSize().Width;
255-
if (double.IsNaN(itemWidth))
256-
{
257-
// We can't calc item's width now
258-
return;
259-
}
260-
261-
this.targetForSizeConstraints.MinWidth = (Math.Min(this.Items.Count, this.MinItemsInRow) * itemWidth) + 0.1;
262-
this.targetForSizeConstraints.MaxWidth = this.MaxItemsInRow == 0
263-
? constraint.Width
264-
: (Math.Min(this.Items.Count, this.MaxItemsInRow) * itemWidth) + 0.1;
265-
}
266-
267-
private void HandleLoaded(object sender, RoutedEventArgs e)
268-
{
269-
this.Loaded -= this.HandleLoaded;
270-
271-
if (this.minMaxWidthNeedsToBeUpdated == false)
272-
{
273-
return;
274-
}
275-
276154
this.InvalidateMeasure();
277155
}
278156

279-
private void HandleUnloaded(object sender, RoutedEventArgs e)
280-
{
281-
this.itemsPanel = null;
282-
283-
this.minMaxWidthNeedsToBeUpdated = true;
284-
}
285-
286-
/// <summary>
287-
/// Determines the desired item size.
288-
/// </summary>
289-
/// <returns>
290-
/// <see cref="Size"/> constructed from <see cref="ItemWidth"/> and <see cref="ItemHeight"/>.
291-
/// If no items are present <see cref="Size.Empty"/>.
292-
/// </returns>
293-
public Size GetItemSize()
294-
{
295-
if (this.Items.Count == 0)
296-
{
297-
return Size.Empty;
298-
}
299-
300-
return new Size(this.ItemWidth, this.ItemHeight);
301-
}
302-
303-
// Finds panel with IsItemsHost, or null if such panel is not found
304-
private static Panel FindItemsPanel(DependencyObject obj)
305-
{
306-
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
307-
{
308-
if (obj is Panel panel &&
309-
panel.IsItemsHost)
310-
{
311-
return panel;
312-
}
313-
314-
panel = FindItemsPanel(VisualTreeHelper.GetChild(obj, i));
315-
if (panel != null)
316-
{
317-
return panel;
318-
}
319-
}
320-
321-
return null;
322-
}
323-
324157
#endregion
325-
326-
/// <inheritdoc />
327-
protected override Size MeasureOverride(Size constraint)
328-
{
329-
if (this.previousItemsCount != this.Items.Count
330-
|| this.minMaxWidthNeedsToBeUpdated)
331-
{
332-
// Track ItemsPanel changes
333-
this.previousItemsCount = this.Items.Count;
334-
this.minMaxWidthNeedsToBeUpdated = true;
335-
336-
this.UpdateMinAndMaxWidth(constraint);
337-
}
338-
339-
if (this.targetForSizeConstraints != null)
340-
{
341-
return base.MeasureOverride(new Size(this.targetForSizeConstraints.MaxWidth, constraint.Height));
342-
}
343-
344-
return base.MeasureOverride(constraint);
345-
// todo: maybe the following code is a better alternative
346-
//if (this.targetForSizeConstraints != null)
347-
//{
348-
// return base.MeasureOverride(new Size(Math.Min(constraint.Width, this.targetForSizeConstraints.MaxWidth), constraint.Height));
349-
//}
350-
351-
//return Size.Empty;
352-
}
353158
}
354159
}

Fluent.Ribbon/Controls/GalleryPanel.cs

+2-75
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,7 @@ public int MinItemsInRow
231231
/// </summary>
232232
public static readonly DependencyProperty MinItemsInRowProperty =
233233
DependencyProperty.Register(nameof(MinItemsInRow), typeof(int),
234-
typeof(GalleryPanel), new PropertyMetadata(1, OnMinItemsInRowChanged));
235-
236-
private static void OnMinItemsInRowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
237-
{
238-
OnMinOrMaxItemsInRowChanged(d, e);
239-
}
234+
typeof(GalleryPanel), new FrameworkPropertyMetadata(1, FrameworkPropertyMetadataOptions.AffectsMeasure));
240235

241236
#endregion
242237

@@ -255,12 +250,7 @@ public int MaxItemsInRow
255250
/// Using a DependencyProperty as the backing store for ItemsInRow.
256251
/// This enables animation, styling, binding, etc...
257252
/// </summary>
258-
public static readonly DependencyProperty MaxItemsInRowProperty = DependencyProperty.Register(nameof(MaxItemsInRow), typeof(int), typeof(GalleryPanel), new PropertyMetadata(0, OnMaxItemsInRowChanged));
259-
260-
private static void OnMaxItemsInRowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
261-
{
262-
OnMinOrMaxItemsInRowChanged(d, e);
263-
}
253+
public static readonly DependencyProperty MaxItemsInRowProperty = DependencyProperty.Register(nameof(MaxItemsInRow), typeof(int), typeof(GalleryPanel), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsMeasure));
264254

265255
#endregion
266256

@@ -306,53 +296,6 @@ protected override Visual GetVisualChild(int index)
306296

307297
#endregion
308298

309-
#region GetActualMinWidth
310-
311-
/// <summary>
312-
/// Updates MinWidth and MaxWidth of the gallery panel (based on MinItemsInRow and MaxItemsInRow)
313-
/// </summary>
314-
public void UpdateMinAndMaxWidth()
315-
{
316-
if (this.areUpdatesSuspsended)
317-
{
318-
return;
319-
}
320-
321-
// Calculate actual min width
322-
double actualMinWidth = 0;
323-
var actualMaxWidth = double.PositiveInfinity;
324-
325-
foreach (var galleryGroupContainer in this.galleryGroupContainers)
326-
{
327-
galleryGroupContainer.MinItemsInRow = this.MinItemsInRow;
328-
galleryGroupContainer.MaxItemsInRow = this.MaxItemsInRow;
329-
330-
InvalidateMeasureRecursive(galleryGroupContainer);
331-
galleryGroupContainer.Measure(SizeConstants.Infinite);
332-
333-
actualMinWidth = Math.Max(actualMinWidth, galleryGroupContainer.MinWidth);
334-
actualMaxWidth = Math.Min(actualMaxWidth, galleryGroupContainer.MaxWidth);
335-
}
336-
337-
this.MinWidth = actualMinWidth;
338-
this.MaxWidth = actualMaxWidth;
339-
}
340-
341-
private static void InvalidateMeasureRecursive(UIElement visual)
342-
{
343-
visual.InvalidateMeasure();
344-
345-
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
346-
{
347-
if (VisualTreeHelper.GetChild(visual, i) is UIElement element)
348-
{
349-
InvalidateMeasureRecursive(element);
350-
}
351-
}
352-
}
353-
354-
#endregion
355-
356299
#region Refresh
357300

358301
private bool areUpdatesSuspsended;
@@ -373,15 +316,6 @@ public void ResumeUpdates()
373316
this.areUpdatesSuspsended = false;
374317
}
375318

376-
/// <summary>
377-
/// Resumes updates and calls <see cref="UpdateMinAndMaxWidth"/>.
378-
/// </summary>
379-
public void ResumeUpdatesAndUpdate()
380-
{
381-
this.ResumeUpdates();
382-
this.UpdateMinAndMaxWidth();
383-
}
384-
385319
/// <summary>
386320
/// Resumes updates and calls <see cref="Refresh"/>.
387321
/// </summary>
@@ -511,7 +445,6 @@ private void Refresh()
511445
this.galleryGroupContainers[0].IsHeadered = false;
512446
}
513447

514-
this.UpdateMinAndMaxWidth();
515448
this.InvalidateMeasure();
516449
}
517450

@@ -585,12 +518,6 @@ protected override Size ArrangeOverride(Size finalSize)
585518

586519
#region Private Methods
587520

588-
private static void OnMinOrMaxItemsInRowChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
589-
{
590-
var galleryPanel = (GalleryPanel)d;
591-
galleryPanel.UpdateMinAndMaxWidth();
592-
}
593-
594521
private string GetPropertyValueAsString(object item)
595522
{
596523
if (item == null

0 commit comments

Comments
 (0)