Absolutely no code behind, probably will not work.
A simple solution is to calculate the logic for converting the height of the window to the number of lines through the converter:
class WindowHeightToRowsConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { var height = (double)value; if (height < 500.0) return 1; else if (height < 700) return 2; else return 3; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
With this, you can make a simple binding:
<Window x:Class="..." ... Width="525" Name="Root"> <Window.Resources> <local:WindowHeightToRowsConverter x:Key="H2R"/> </Window.Resources> <Grid> <ListBox ItemsSource="..."> <ListBox.ItemsPanel> <ItemsPanelTemplate> <UniformGrid IsItemsHost="True" Rows="{Binding ActualHeight, ElementName=Root, Converter={StaticResource H2R}}"/> </ItemsPanelTemplate> </ListBox.ItemsPanel> </ListBox> </Grid> </Window>
The disadvantage of this solution is that the WindowHeightToRowsConverter class WindowHeightToRowsConverter very specific and difficult to reuse. A more complex, but potentially reusable solution, for example, is.
Put comparing converters:
class LessThanConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (double)value < (double)parameter; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } class GreaterOrEqConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (double)value >= (double)parameter; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } }
Now, for convenience, specifying constants in the code here is such a thing:
public class DoubleExtension : MarkupExtension { public DoubleExtension(double value) { Value = value; } public double Value { get; set; } public override object ProvideValue(IServiceProvider sp) { return Value; } }
We write the following XAML:
<Window x:Class="..." 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" xmlns:local="..." ... Name="Root"> <Window.Resources> <local:LessThanConverter x:Key="LT"/> <local:GreaterOrEqConverter x:Key="GE"/> </Window.Resources>
<UniformGrid IsItemsHost="True"> <UniformGrid.Style> <Style TargetType="UniformGrid"> <Setter Property="Rows" Value="1"/> <Style.Triggers> <MultiDataTrigger> <MultiDataTrigger.Conditions> <!-- если высота >= 500... --> <Condition Binding="{Binding ActualHeight, ElementName=Root, Converter={StaticResource GE}, ConverterParameter={local:Double 500}}" Value="True"/> <!-- и < 700... --> <Condition Binding="{Binding ActualHeight, ElementName=Root, Converter={StaticResource LT}, ConverterParameter={local:Double 700}}" Value="True"/> </MultiDataTrigger.Conditions> <!-- то Rows = 2 --> <Setter Property="Rows" Value="2"/> </MultiDataTrigger> <MultiDataTrigger> <MultiDataTrigger.Conditions> <!-- если высота >= 700... --> <Condition Binding="{Binding ActualHeight, ElementName=Root, Converter={StaticResource GE}, ConverterParameter={local:Double 700}}" Value="True"/> </MultiDataTrigger.Conditions> <!-- то Rows = 3 --> <Setter Property="Rows" Value="3"/> </MultiDataTrigger> </Style.Triggers> </Style> </UniformGrid.Style> </UniformGrid>
This way you can combine simple conditions into complex ones.
( local:Double works with DoubleExtension .)
xaml? - Lightness