6

WPF のグリッドには現在、次のようなグリッド システムがあります。

    Cols
   +   +   +   +   +
   | 0 | 1 | 2 | 3 | 
+--+---|---|---|---|---
 0 |   |   |   |   |
+--+---|---|---|---|---  Rows
 1 |   |   |   |   |   
+--+---|---|---|---|---
 2 |   |   |   |   | 
+--+---|---|---|---|---

次のように動作させる方法はありますか?

    Cols
   +   +   +   +   +
   | 0 | 1 | 2 | 3 | 
+--+---|---|---|---|---
 2 |   |   |   |   |
+--+---|---|---|---|---  Rows
 1 |   |   |   |   |   
+--+---|---|---|---|---
 0 |   |   |   |   | 
+--+---|---|---|---|---

理想的には、RowSpan で項目を下方向ではなく上方向に拡張したいと考えています。

例:

私のデータソースは、マップ上の立方体を 0,0 として保存し、左下隅に表示することを意図しています。ただし、WPF のグリッドはその立方体を左上に配置します。もう1つの問題は、データソースが幅と高さのある左下の「アンカー」位置の2x2を提供することです。幅と高さは、ColSpan と RowSpan にバインドされています。RowSpan は、グリッドの上ではなく下に展開されるため、問題になります。

4

5 に答える 5

1

このコンバーターを試してください。XAMLは少し複雑に見えますが、ViewModel(s)やUserControl(s)は必要ありません。

行を反転するためのコンバーター:

public class UpsideDownRowConverter : IMultiValueConverter
{
    public int RowCount
    {
        get;
        set;
    }

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values.Length == 2 && values[0] is int && values[1] is int)
        {
            var row = (int)values[0];
            var rowSpan = (int)values[1];

            row = this.RowCount - row - rowSpan;

            return row;
        }

        return DependencyProperty.UnsetValue;
    }

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

XAML。最初のグリッドはオリジナルで、2番目のグリッドは反転しています。

<Window.Resources>
    <local:UpsideDownRowConverter x:Key="UpsideDownRowConverter"
                                    RowCount="3"/>
</Window.Resources>
<UniformGrid Rows="2">
    <Grid Name="Original"
            Margin="0,0,0,10">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Rectangle Fill="Green"
                    Grid.Column="0"
                    Grid.Row="2"/>
        <Rectangle Fill="Red"
                    Grid.Column="1"
                    Grid.Row="1"/>
        <Rectangle Fill="Blue"
                    Grid.Column="2"
                    Grid.RowSpan="3"/>
        <Rectangle Fill="Yellow"
                    Grid.Column="3"
                    Grid.RowSpan="2"/>
    </Grid>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Rectangle Fill="Green"
                    Grid.Column="0">
            <Grid.Row>
                <MultiBinding Converter="{StaticResource UpsideDownRowConverter}">
                    <Binding Path="Children[0].(Grid.Row)"
                                ElementName="Original"/>
                    <Binding Path="(Grid.RowSpan)"
                                RelativeSource="{RelativeSource Self}"/>
                </MultiBinding>
            </Grid.Row>
        </Rectangle>
        <Rectangle Fill="Red"
                    Grid.Column="1">
            <Grid.Row>
                <MultiBinding Converter="{StaticResource UpsideDownRowConverter}">
                    <Binding Path="Children[1].(Grid.Row)"
                                ElementName="Original"/>
                    <Binding Path="(Grid.RowSpan)"
                                RelativeSource="{RelativeSource Self}"/>
                </MultiBinding>
            </Grid.Row>
        </Rectangle>
        <Rectangle Fill="Blue"
                    Grid.Column="2"
                    Grid.RowSpan="3">
            <Grid.Row>
                <MultiBinding Converter="{StaticResource UpsideDownRowConverter}">
                    <Binding Path="Children[2].(Grid.Row)"
                                ElementName="Original"/>
                    <Binding Path="(Grid.RowSpan)"
                                RelativeSource="{RelativeSource Self}"/>
                </MultiBinding>
            </Grid.Row>
        </Rectangle>
        <Rectangle Fill="Yellow"
                    Grid.Column="3"
                    Grid.RowSpan="2">
            <Grid.Row>
                <MultiBinding Converter="{StaticResource UpsideDownRowConverter}">
                    <Binding Path="Children[3].(Grid.Row)"
                                ElementName="Original"/>
                    <Binding Path="(Grid.RowSpan)"
                                RelativeSource="{RelativeSource Self}"/>
                </MultiBinding>
            </Grid.Row>
        </Rectangle>
    </Grid>
</UniformGrid>

残念ながら、RowDefinitionCollectionは変更について通知しないため、行数を3番目の値として渡すことはできません。そのため、コンバーターのプロパティとしてRowCountを追加しました。

于 2012-04-26T11:13:53.787 に答える
1

添付プロパティを使用して、カスタム コントロールまたはユーザー コントロールを作成しなくても、これを実行できるはずです。

これは、あなたがやりたいことができるはずだと思うクラスです。Grid.Rowandの値をGrid.RowSpan行と高さにバインドする代わりに、GridEx.RowFromBottomandGridEx.RowSpanFromBottomをそれらにバインドします。これらのプロパティのプロパティ変更ハンドラーは、それらのプロパティGrid.Rowの値とグリッド内の行数に基づいて の新しい値を計算します。

潜在的な問題の 1 つは、実行時にグリッドから行を追加または削除している場合、これが正しく更新されない可能性があることです。

public static class GridEx
{
    public static readonly DependencyProperty RowFromBottomProperty = DependencyProperty.RegisterAttached("RowFromBottom", typeof(int?), typeof(GridEx), new FrameworkPropertyMetadata(default(int?), FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsParentMeasure, OnRowFromBottomChanged));
    public static readonly DependencyProperty RowSpanFromBottomProperty = DependencyProperty.RegisterAttached("RowSpanFromBottom", typeof(int?), typeof(GridEx), new FrameworkPropertyMetadata(default(int?), FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsParentArrange | FrameworkPropertyMetadataOptions.AffectsParentMeasure, OnRowSpanFromBottomChanged));

    private static void OnRowFromBottomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var grid = GetContainingGrid(d);
        int? rowFromBottom = (int?) e.NewValue;
        int? rowSpanFromBottom = GetRowSpanFromBottom(d);
        if (rowFromBottom == null || rowSpanFromBottom == null) return;
        int rows = grid.RowDefinitions.Count;
        int row = Math.Max(0, Math.Min(rows, rows - rowFromBottom.Value - rowSpanFromBottom.Value));
        Grid.SetRow((UIElement) d, row);
    }

    private static void OnRowSpanFromBottomChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var grid = GetContainingGrid(d);
        int? rowFromBottom = GetRowFromBottom(d);
        int? rowSpanFromBottom = (int?)e.NewValue;
        if (rowFromBottom == null || rowSpanFromBottom == null) return;
        int rows = grid.RowDefinitions.Count;
        int row = Math.Max(0, Math.Min(rows, rows - rowFromBottom.Value - rowSpanFromBottom.Value));
        Grid.SetRow((UIElement)d, row);
        Grid.SetRowSpan((UIElement)d, rowSpanFromBottom.Value);
    }

    public static int? GetRowFromBottom(DependencyObject obj)
    {
        return (int?) obj.GetValue(RowFromBottomProperty);
    }

    public static void SetRowFromBottom(DependencyObject obj, int? value)
    {
        obj.SetValue(RowFromBottomProperty, value);
    }

    public static int? GetRowSpanFromBottom(DependencyObject obj)
    {
        return (int?)obj.GetValue(RowSpanFromBottomProperty);
    }

    public static void SetRowSpanFromBottom(DependencyObject obj, int? value)
    {
        obj.SetValue(RowSpanFromBottomProperty, value);
    }

    private static Grid GetContainingGrid(DependencyObject element)
    {
        Grid grid = null;
        while (grid == null && element != null)
        {
            element = LogicalTreeHelper.GetParent(element);
            grid = element as Grid;
        }
        return grid;
    }
}

ここで何が起こっているのかについて質問がある場合は、お気軽にお尋ねください。

于 2012-04-26T03:58:20.910 に答える
1

これは、独自のカスタム コントロールを作成することで実現できます。から継承することも、 a をGrid使用しUserControlて a を使用することもできGridます。どちらの方法でも、 と同様に添付プロパティを提供し、Grid必要に応じて値を操作して、基になる に渡すことができますGrid

于 2012-04-05T22:01:24.017 に答える
1

Grid立方体を表示している場所は固定サイズですか? その場合、ビューで機能するためにモデル座標を変換/反転する ViewModel を作成することを検討できます。つまり、キューブには値が(0,0)あり、ViewModel はその値を として公開します(0,2)

自分でコントロールするよりも簡単なアイデアです。

于 2012-04-05T23:48:14.993 に答える
0

次のように、行を逆形式に変換できます。

    private void ReverseRow(Grid grd)
    {
        int totalRows = grd.RowDefinitions.Count-1;
        foreach (UIElement ctl in grd.Children)
        {
            int currentRowIndex = Grid.GetRow(ctl);
            Grid.SetRow(ctl, totalRows - currentRowIndex);
        }
    }

これにより、行が元に戻ります。

于 2012-05-01T06:05:41.567 に答える