8

たぶん、皆さんは私がこれを理解するのを手伝ってくれるかもしれません.Dictionaryと、その辞書にバインドされているItemsControlがあります。各エントリのキーは、ItemsControl 内の各アイテムの内容を決定し、値は各アイテムの幅を決定します。これに関する大きな問題: 幅はパーセンテージ値であるため、たとえば、アイテムのサイズが親の 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>

これに関するアイデアはありますか?これを解決するエレガントな方法はありますか?

ありがとう!

明確化: パーセンテージは、ItemControls 親に基づいているはずです!

もう 1 つ: 各項目は、行ではなく、グリッドの 1 つの列であると想定されています。したがって、すべてのアイテムを同じ行に並べる必要があります。

解決策

ご協力ありがとうございます。この問題は、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>

コンバーター:

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();
    }
}

そして、それはトリックを行う必要があります!

4

3 に答える 3

9

を実装できます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>

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();
    }
}

3)ビューモデル:

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

    public Double RelativeWidth
    {
        get { return relativeWidth; }
        set
        {
            if (relativeWidth != value)
            {
                relativeWidth = value;
                OnPropertyChanged("RelativeWidth");
            }
        }
    }
    private Double relativeWidth;
}

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 },
        };
    }
}

MultiBinding変更されると、バインディングターゲットを強制的に更新しActualWidthます。

于 2012-08-08T13:06:21.643 に答える
0

グリッドを使用できない必要がありました。

コンテンツをラップして動的なパーセンテージの幅/高さを追加できる ContentControl を作成しました。

/// <summary>
/// This control has a dynamic/percentage width/height
/// </summary>
public class FluentPanel : ContentControl, IValueConverter
{
    #region Dependencie Properties

    public static readonly DependencyProperty WidthPercentageProperty =
        DependencyProperty.Register("WidthPercentage", typeof(int), typeof(FluentPanel), new PropertyMetadata(-1, WidthPercentagePropertyChangedCallback));

    private static void WidthPercentagePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        ((FluentPanel)dependencyObject).OnWidthPercentageChange();
    }

    public int WidthPercentage
    {
        get { return (int)GetValue(WidthPercentageProperty); }
        set { SetValue(WidthPercentageProperty, value); }
    }

    public static readonly DependencyProperty HeightPercentageProperty =
        DependencyProperty.Register("HeightPercentage", typeof(int), typeof(FluentPanel), new PropertyMetadata(-1, HeightPercentagePropertyChangedCallback));

    private static void HeightPercentagePropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        ((FluentPanel)dependencyObject).OnHeightPercentageChanged();
    }

    public int HeightPercentage
    {
        get { return (int)GetValue(HeightPercentageProperty); }
        set { SetValue(HeightPercentageProperty, value); }
    }

    #endregion

    #region Methods

    private void OnWidthPercentageChange()
    {
        if (WidthPercentage == -1)
        {
            ClearValue(WidthProperty);
        }
        else
        {
            SetBinding(WidthProperty, new Binding("ActualWidth") { Source = Parent, Converter = this, ConverterParameter = true });
        }
    }

    private void OnHeightPercentageChanged()
    {
        if (HeightPercentage == -1)
        {
            ClearValue(HeightProperty);
        }
        else
        {
            SetBinding(HeightProperty, new Binding("ActualHeight") { Source = Parent, Converter = this, ConverterParameter = false });
        }
    }

    #endregion

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if ((bool)parameter)
        {
            // width
            return (double)value * (WidthPercentage * .01);
        }
        else
        {
            // height
            return (double)value * (HeightPercentage * .01);
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}
于 2013-08-08T02:04:55.677 に答える
0

Gridに aを入れてみてくださいItemTemplate。これGridには 2 つの列があります。1 つは実際のコンテンツ用で、もう 1 つは空きスペース用です。辞書の を使用して、これらの列の幅をバインドできるはずです。ValueおそらくIValueConverter.

コンテンツを中央に配置する必要がある場合は、3 つの列を作成して、空のスペースを列 0 と 2 に分割する必要があります。

于 2012-08-08T13:03:59.977 に答える