WPF中基于动态百分比的宽度

Bla*_*olf 7 c# wpf grid dynamic width

也许你们可以帮我解决这个问题:我有一个字典和一个与该字典结合的ItemsControl.每个条目的Key确定ItemsControl中每个Item的内容,Value确定每个Item的宽度.这个问题很大:宽度是一个百分比值,所以它告诉我,例如,我的Item需要是其父级的20%.

我怎样才能做到这一点?我知道网格能够处理基于星的宽度,但由于我必须在网格的开头定义GridDefinition,我不能在ItemsControl.ItemTemplate中执行此操作.

当前代码:

<ItemsControl ItemsSource="{Binding Distribution}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> 
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid IsItemsHost="True" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel> 
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <!-- I NEED THIS TO BE A CERTAIN PERCENTAGE IN WIDTH -->
                <Label Content="{Binding Key.Text}" Foreground="{Binding Key.Color}"/> 
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?有没有优雅的方法来解决这个问题?

谢谢!

澄清:百分比应该基于ItemControls父级!

另一个:每个项目应该是网格的一列,而不是一行.所以我需要所有项目在同一行中彼此相邻.

解决方案:

感谢您的帮助,可以通过使用Multibinding和Binding到ItemsControl的ActualWidth来解决此问题.这样,只要ItemsControl的大小发生变化,Items也会发生变化.不需要网格.此解决方案仅创建相对宽度,但当然可以将相同的解决方案应用于项目的高度.这是一个简短的版本,有关更全面的解释,请参见下文:

XAML:

<ItemsControl ItemsSource="{Binding Distribution}" Name="itemsControl"  HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
         <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel IsItemsHost="True" Orientation="Horizontal" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel> 
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Label Content="{Binding Key.Text}" 
                       Foreground="{Binding Key.Color}">
                    <Label.Width>
                        <MultiBinding Converter="{StaticResource myConverter}">
                            <Binding Path="Value"/>
                            <Binding Path="ActualWidth" ElementName="itemsControl"/>
                        </MultiBinding>
                    </Label.Width>
                </Label>  
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
Run Code Online (Sandbox Code Playgroud)

转换器:

class MyConverter : IMultiValueConverter
{
    public object Convert(object[] value, Type targetType, object parameter, CultureInfo culture)
    {
        //[1] contains the ItemsControl.ActualWidth we binded to, [0] the percentage
        //In this case, I assume the percentage is a double between 0 and 1
        return (double)value[1] * (double)value[0];
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该是诀窍!

Den*_*nis 8

你可以实现IValueConverter.

更新.

MultiBinding会帮助你.这是样本:

1)xaml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="114" Width="404">
    <Grid>
        <Grid.Resources>
            <local:RelativeWidthConverter x:Key="RelativeWidthConverter"/>
        </Grid.Resources>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        <ItemsControl ItemsSource="{Binding}"
                      x:Name="itemsControl">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Rectangle Fill="Green" Margin="5" Height="20" HorizontalAlignment="Left">
                        <Rectangle.Width>
                            <MultiBinding Converter="{StaticResource RelativeWidthConverter}">
                                <Binding Path="RelativeWidth"/>
                                <Binding Path="ActualWidth" ElementName="itemsControl"/>
                            </MultiBinding>
                        </Rectangle.Width>
                    </Rectangle> 
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
    </Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)

2)转换器:

public class RelativeWidthConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return ((Double)values[0] * (Double)values[1]) / 100.0;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

3)查看模型:

public class ViewModel : ViewModelBase
{
    public ViewModel()
    {
    }

    public Double RelativeWidth
    {
        get { return relativeWidth; }
        set
        {
            if (relativeWidth != value)
            {
                relativeWidth = value;
                OnPropertyChanged("RelativeWidth");
            }
        }
    }
    private Double relativeWidth;
}
Run Code Online (Sandbox Code Playgroud)

4)代码隐藏:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new[] 
        { 
            new ViewModel { RelativeWidth = 20 },
            new ViewModel { RelativeWidth = 40 },
            new ViewModel { RelativeWidth = 60 },
            new ViewModel { RelativeWidth = 100 },
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

MultiBindingActualWidth更改时强制更新绑定目标.