Skip to main content
Home Forums Silverlight Programming Report a Silverlight Bug [RTW] ComboBox ScaleTransform, Sizing bugs
2 replies. Latest Post by mikealex on November 9, 2008.
(0)
simon.fe...
Member
158 points
48 Posts
10-15-2008 5:04 AM |
Hi,
When you put a scale transform on a ComboBox (or on an element containing a ComboBox), its popup sizing logic does not work well : If its itemsource contains too much elements, its maximum height does not take care of the ScaleTransform currently applied, and some data get out of the Window.
See the sample below to have a repro :
<UserControl x:Class="BugComboboxSizing.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" > <Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.5*" /> <ColumnDefinition Width="0.5*" /> </Grid.ColumnDefinitions> <Border HorizontalAlignment="Center" VerticalAlignment="Center"> <ComboBox > <sys:String>Item 1</sys:String> <sys:String>Item 2</sys:String> <sys:String>Item 3</sys:String> <sys:String>Item 4</sys:String> <sys:String>Item 5</sys:String> <sys:String>Item 6</sys:String> <sys:String>Item 7</sys:String> <sys:String>Item 8</sys:String> <sys:String>Item 9</sys:String> <sys:String>Item 1</sys:String> <sys:String>Item 2</sys:String> <sys:String>Item 3</sys:String> <sys:String>Item 4</sys:String> <sys:String>Item 5</sys:String> <sys:String>Item 6</sys:String> <sys:String>Item 7</sys:String> <sys:String>Item 8</sys:String> <sys:String>Item 9</sys:String> <sys:String>Item 1</sys:String> <sys:String>Item 2</sys:String> <sys:String>Item 3</sys:String> <sys:String>Item 4</sys:String> <sys:String>Item 5</sys:String> <sys:String>Item 6</sys:String> <sys:String>Item 7</sys:String> <sys:String>Item 8</sys:String> <sys:String>Item 9</sys:String> <sys:String>Item 1</sys:String> <sys:String>Item 2</sys:String> <sys:String>Item 3</sys:String> <sys:String>Item 4</sys:String> <sys:String>Item 5</sys:String> <sys:String>Item 6</sys:String> <sys:String>Item 7</sys:String> <sys:String>Item 8</sys:String> <sys:String>Item 9</sys:String> </ComboBox> </Border> <Border HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Column="1"> <ComboBox > <ComboBox.RenderTransform> <ScaleTransform CenterX="0.5" CenterY="0.5" ScaleX="2" ScaleY="2" /> </ComboBox.RenderTransform> <sys:String>Item 1</sys:String> <sys:String>Item 2</sys:String> <sys:String>Item 3</sys:String> <sys:String>Item 4</sys:String> <sys:String>Item 5</sys:String> <sys:String>Item 6</sys:String> <sys:String>Item 7</sys:String> <sys:String>Item 8</sys:String> <sys:String>Item 9</sys:String> <sys:String>Item 1</sys:String> <sys:String>Item 2</sys:String> <sys:String>Item 3</sys:String> <sys:String>Item 4</sys:String> <sys:String>Item 5</sys:String> <sys:String>Item 6</sys:String> <sys:String>Item 7</sys:String> <sys:String>Item 8</sys:String> <sys:String>Item 9</sys:String> <sys:String>Item 1</sys:String> <sys:String>Item 2</sys:String> <sys:String>Item 3</sys:String> <sys:String>Item 4</sys:String> <sys:String>Item 5</sys:String> <sys:String>Item 6</sys:String> <sys:String>Item 7</sys:String> <sys:String>Item 8</sys:String> <sys:String>Item 9</sys:String> <sys:String>Item 1</sys:String> <sys:String>Item 2</sys:String> <sys:String>Item 3</sys:String> <sys:String>Item 4</sys:String> <sys:String>Item 5</sys:String> <sys:String>Item 6</sys:String> <sys:String>Item 7</sys:String> <sys:String>Item 8</sys:String> <sys:String>Item 9</sys:String> </ComboBox> </Border> </Grid> </UserControl>
After checks with reflector, the problem seems to be in in the method: ComboBox::ArrangePopup() which get the offsetX and offsetY of the general transform, but not ScaleX and ScaleY.
I have authored a SuggestBox control (that has the same kind of logic for sizing the suggestions area). Here is it's sizing code (that works well):
var gt = _popup.TransformToVisual(page) as MatrixTransform; double yOffset = 0.0; double yScale = 1.0; if (gt != null) { yOffset = gt.Matrix.OffsetY; yScale = gt.Matrix.M22; } var pageHeight = page.ActualHeight; var availableHeight = pageHeight - yOffset; var scaledMaxHeight = availableHeight / yScale;
One other thing that does not make good behavior is the following actions on the previous sample :
This behavior is kind of weird and can be reproduced in a more blocking way in a business environment
Sorry to not have detect these bugs before RTW, I just figured out of them last night.
Simon Ferquel
10-21-2008 6:10 AM |
For those who are facing these bugs, I have a quick workaround not deeply tested but that seems to work efficiently :
public
{
Popup _popup;
FrameworkElement _elementPopupChild;
public override void OnApplyTemplate()
_popup = GetTemplateChild("Popup") as Popup;
_elementPopupChild = _popup.Child as FrameworkElement;
base.OnApplyTemplate();
}
protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
base.OnItemsChanged(e);
if (_elementPopupChild != null)
_elementPopupChild.ClearValue(FrameworkElement.MinWidthProperty);
_elementPopupChild.ClearValue(FrameworkElement.MinHeightProperty);
_elementPopupChild.ClearValue(FrameworkElement.MaxWidthProperty);
_elementPopupChild.ClearValue(FrameworkElement.MaxHeightProperty);
_elementPopupChild.ClearValue(FrameworkElement.WidthProperty);
_elementPopupChild.ClearValue(FrameworkElement.HeightProperty);
this.InvalidateArrange();
protected override void OnDropDownOpened(EventArgs e)
base.OnDropDownOpened(e);
if (_elementPopupChild == null)
return;
FrameworkElement page = Application.Current.RootVisual as FrameworkElement;
var gt = _popup.TransformToVisual(page) as MatrixTransform;
double yOffset = 0.0;
double yScale = 1.0;
if (gt != null)
yOffset = gt.Matrix.OffsetY;
yScale = gt.Matrix.M22;
var pageHeight = page.ActualHeight;
var availableHeight = pageHeight - yOffset;
var scaledMaxHeight = availableHeight / yScale - this.ActualHeight;
if(_elementPopupChild.MaxHeight != double.NaN && _elementPopupChild.MaxHeight != double.PositiveInfinity)
scaledMaxHeight = Math.Min(scaledMaxHeight, _elementPopupChild.MaxHeight);
_elementPopupChild.MaxHeight = scaledMaxHeight > 0 ? scaledMaxHeight : 0;
mikealex
3 points
10 Posts
11-09-2008 3:46 PM |
There is another Scale-related bug in that the mouse position on the dropdown's scrollbar is scaled incorrectly, meaning that the relative position of the mouse pointer and scrollbar moves as you drag it.
Try the following:
<UserControl x:Class="TestBed.Page" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="300" Height="400">
<UserControl.RenderTransform> <ScaleTransform ScaleX="2" ScaleY="2"></ScaleTransform> </UserControl.RenderTransform> <Canvas Width="300" Height="400" x:Name="LayoutRoot"> <ComboBox Height="20" Width="100" MaxDropDownHeight="200"> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> <ComboBoxItem Content="Text" /> </ComboBox> </Canvas></UserControl>
Click the down-arrow to cause the dropdown to display. Note that if you grab the scrollbar "thumb" near the top of the thumb, and drag it down, the thumb moves at twice the speed of the mouse, meaning that the mouse cursor eventually moves off the thumb. At higher scale factors this can be a real problem, as the thumb flies along at "Scale x" the actual mouse speed.
The suggested fixed Combox Box doesn't make a difference to this behaviour.
Best Regards,
Mike